Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lglpy/timeline/data/raw_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,19 +878,22 @@ def load_perfetto_from_file(
# Sort events into time order
trace_events.sort(key=lambda x: x.start_time)

# Replace time so first event starts at time = 0
# Replace time so first event starts at time = 0 and that queued time
# waiting for earlier work does not show as running
streams = {}
start_time = trace_events[0].start_time
for event in trace_events:
event.start_time -= start_time

# Also ensure that queued time does not show as running
# First job in stream so just add to stream
if event.stream not in streams:
streams[event.stream] = [event]
continue

# Later job in stream so remove any overlap with job N-1
last_event = streams[event.stream][-1]
last_event_end = last_event.start_time + last_event.duration
streams[event.stream].append(event)

# Remove overlap if queued while last event still running
if event.start_time <= last_event_end:
Expand Down
65 changes: 63 additions & 2 deletions lglpy/timeline/gui/timeline/info_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

from collections import defaultdict

from ...data.raw_trace import GPUStreamID
from ...data.raw_trace import GPUStreamID, GPUStageID
from ...data.processed_trace import GPUWorkload
from ...drawable.text_pane_widget import TextPaneWidget

Expand Down Expand Up @@ -251,13 +251,71 @@ def get_active_region_stats(self):

return self.cached_range_info

def compute_active_event_stats_single(self, event):
'''
Get the metrics for the active event.

This function uses a cached lookup to avoid re-calculating every
redraw, as the stats computation can be quite slow.

Args:
event: The active event.

Returns:
List of lines to be printed.
'''
# Skip non-workload types
if not isinstance(event, GPUWorkload):
return []

stream_name = GPUStreamID.get_ui_name(event.stream)
stage_name = GPUStageID.get_ui_name(event.stage)

metrics = ['']

# Report total runtime of the selected workloads
other_names = [
'API workloads:',
'Hardware workloads:'
]

metrics.append('Active workload runtime:')
label_len = len(stream_name) + len(' stream:')
label_len = max(max(len(x) for x in other_names), label_len)

label = other_names[0]
metrics.append(f' {label:{label_len}} {1:>5}')

label = other_names[1]
metrics.append(f' {label:{label_len}} {1:>5}')

label = f'{stream_name} stream:'
duration = float(event.duration) / 1000000.0
metrics.append(f' {label:{label_len}} {duration:>5.2f} ms')

# Report total N workloads
metrics.append('')
metrics.append('Workload properties:')

label = event.get_workload_name()
metrics.append(f' Name: {label}')
metrics.append(f' Stream: {stream_name}')
metrics.append(f' Stage: {stage_name}')
metrics.append(f' Start: {event.start_time / 1000000.0:0.2f} ms')
metrics.append(f' Duration: {event.duration / 1000000.0:0.2f} ms')
metrics.append('')
return metrics

def compute_active_event_stats_multi(self, active):
'''
Get the metrics for the active time range.
Get the metrics for the active events.

This function uses a cached lookup to avoid re-calculating every
redraw, as the stats computation can be quite slow.

Args:
active: List of active events.

Returns:
List of lines to be printed.
'''
Expand Down Expand Up @@ -368,6 +426,9 @@ def get_active_event_stats(self):
if len(active) == 0:
info = None

elif len(active) == 1:
info = self.compute_active_event_stats_single(active[0])

else:
info = self.compute_active_event_stats_multi(active)

Expand Down