|
5 | 5 |
|
6 | 6 | import numpy as np |
7 | 7 | import pandas as pd |
| 8 | + |
| 9 | +import pipit |
8 | 10 | from pipit.util.cct import create_cct |
9 | 11 |
|
10 | 12 |
|
@@ -896,3 +898,77 @@ def detect_pattern( |
896 | 898 | patterns.append(match_original) |
897 | 899 |
|
898 | 900 | return patterns |
| 901 | + |
| 902 | + def time_breakdown(self): |
| 903 | + # Time breakdown by annotation |
| 904 | + # Counts time in annotation |
| 905 | + # + time in launched kernels |
| 906 | + ann_events = self.events[ |
| 907 | + (self.events["type"] == "annotation") & |
| 908 | + (self.events["Event Type"] == "Enter") |
| 909 | + ] |
| 910 | + |
| 911 | + # TODO: provide breakdowns within annotation |
| 912 | + # as well? |
| 913 | + |
| 914 | + # Amount of time we spend in the label |
| 915 | + # TODO: can break this down further into CUDA API/kernel launch |
| 916 | + # time, and other events |
| 917 | + cpu_time = ann_events.groupby("Name")["time.inc"].sum() |
| 918 | + |
| 919 | + ann_kernel_times = pd.Series([0] * len(cpu_time), index=cpu_time.index, name="time.inc") |
| 920 | + |
| 921 | + def _calc_kernel_time(row): |
| 922 | + # locate the launch event for the kernel |
| 923 | + # and binary search the start time of the launch |
| 924 | + # event in annotation events in order to find the |
| 925 | + # corresponding annotation |
| 926 | + parent = row["_parent"] |
| 927 | + # note: parent is always an enter event |
| 928 | + launch_start = self.events.loc[parent, "Timestamp (ns)"] |
| 929 | + # we don't use annotation df from above, since we need |
| 930 | + # leave events also here |
| 931 | + ann_df = self.events[self.events["type"] == "annotation"] |
| 932 | + idx = np.searchsorted(ann_df["Timestamp (ns)"], launch_start) |
| 933 | + |
| 934 | + ann_event = ann_df.iloc[idx] |
| 935 | + ann_kernel_times.loc[ann_event["Name"]] += row["time.inc"] |
| 936 | + # dummy return |
| 937 | + # TODO: maybe there is a more efficient/cleaner way to do this |
| 938 | + return 0 |
| 939 | + |
| 940 | + kernels = self.events[ |
| 941 | + (self.events["type"] == "kernel") & |
| 942 | + (self.events["Event Type"] == "Enter") |
| 943 | + ] |
| 944 | + kernels.apply( |
| 945 | + _calc_kernel_time, |
| 946 | + axis=1, |
| 947 | + ) |
| 948 | + return cpu_time + ann_kernel_times |
| 949 | + |
| 950 | + def filter_by_label(self, label_name): |
| 951 | + """ |
| 952 | + Filters trace to find kernels |
| 953 | + that occurred during this time frame |
| 954 | + and their associated launch events |
| 955 | + """ |
| 956 | + # Find the annotations |
| 957 | + events = self.events |
| 958 | + annotation = events[ |
| 959 | + (events["Name"] == label_name) & (events["type"] == "annotation") |
| 960 | + ] |
| 961 | + assert (len(annotation) == 2) |
| 962 | + # This is OK since we sorted by time |
| 963 | + # TODO: we should do more error checking here though |
| 964 | + start = annotation.iloc[0]["Timestamp (ns)"] |
| 965 | + end = annotation.iloc[1]["Timestamp (ns)"] |
| 966 | + |
| 967 | + # Filter events to find those with timestamp in range |
| 968 | + return Trace( |
| 969 | + None, |
| 970 | + events[ |
| 971 | + (events["Timestamp (ns)"] >= start) & (events["Timestamp (ns)"] <= end) |
| 972 | + ], |
| 973 | + self.parallelism_levels |
| 974 | + ) |
0 commit comments