Skip to content

Commit 7966c5d

Browse files
Olivia-liufacebook-github-bot
authored andcommitted
Inspector APIs documentation - inline docstring part (#626)
Summary: Pull Request resolved: #626 As titled Reviewed By: tarun292 Differential Revision: D49893649 fbshipit-source-id: ab2fc8db5dd164056213a51294842655776c4a5e
1 parent a77faff commit 7966c5d

File tree

2 files changed

+72
-31
lines changed

2 files changed

+72
-31
lines changed

sdk/inspector/inspector.py

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -129,28 +129,34 @@ def median(self) -> float:
129129
@dataclass
130130
class Event:
131131
"""
132-
Corresponds to an op instance
132+
An Event corresponds to an operator instance with perf data retrieved from the runtime and other metadata from `ETRecord`.
133+
134+
Args:
135+
name: Name of the profiling/debugging `Event`.
136+
perf_data: Performance data associated with the event retrived from the runtime (available attributes: p50, p90, avg, min, max and median).
137+
op_type: List of op types corresponding to the event.
138+
delegate_debug_identifier: Supplemental identifier used in combination with instruction id.
139+
debug_handles: Debug handles in the model graph to which this event is correlated.
140+
stack_trace: A dictionary mapping the name of each associated op to its stack trace.
141+
module_hierarchy: A dictionary mapping the name of each associated op to its module hierarchy.
142+
is_delegated_op: Whether or not the event was delegated.
143+
delegate_backend_name: Name of the backend this event was delegated to.
144+
debug_data: Intermediate data collected during runtime.
133145
"""
134146

135147
name: str
136148
perf_data: PerfData
137149
op_types: List[str] = dataclasses.field(default_factory=list)
138-
139-
# Instruction Id of the original profiling event
140-
instruction_id: Optional[int] = None
141-
142-
# Supplemental Identifier used in combination with instruction_identifier
143150
delegate_debug_identifier: Optional[Union[int, str]] = None
144-
145-
# Debug Handles in the model graph to which this event is correlated
146151
debug_handles: Optional[Union[int, Sequence[int]]] = None
147-
148152
stack_traces: Dict[str, str] = dataclasses.field(default_factory=dict)
149153
module_hierarchy: Dict[str, Dict] = dataclasses.field(default_factory=dict)
150154
is_delegated_op: Optional[bool] = None
151155
delegate_backend_name: Optional[str] = None
152156
debug_data: List[torch.Tensor] = dataclasses.field(default_factory=list)
153157

158+
_instruction_id: Optional[int] = None
159+
154160
@staticmethod
155161
def _gen_from_profile_events(
156162
signature: ProfileEventSignature,
@@ -183,9 +189,9 @@ def _gen_from_profile_events(
183189
return Event(
184190
name=name,
185191
perf_data=perf_data,
186-
instruction_id=signature.instruction_id,
187192
delegate_debug_identifier=delegate_debug_identifier,
188193
is_delegated_op=is_delegated_op,
194+
_instruction_id=signature.instruction_id,
189195
)
190196

191197
def _associate_with_op_graph_nodes(
@@ -213,11 +219,14 @@ def _associate_with_op_graph_nodes(
213219

214220
@dataclass
215221
class EventBlock:
216-
"""
217-
EventBlock contains a collection of events associated with a particular profiling/debugging block retrieved from the runtime.
218-
Attributes:
219-
name (str): Name of the profiling/debugging block
220-
events (List[Event]): List of events associated with the profiling/debugging block
222+
r"""
223+
An `EventBlock` contains a collection of events associated with a particular profiling/debugging block retrieved from the runtime.
224+
Each `EventBlock` represents a pattern of execution. For example, model initiation and loading lives in a single `EventBlock`.
225+
If there's a control flow, each branch will be represented by a separate `EventBlock`.
226+
227+
Args:
228+
name: Name of the profiling/debugging block.
229+
events: List of `Event`\ s associated with the profiling/debugging block.
221230
"""
222231

223232
name: str
@@ -226,7 +235,14 @@ class EventBlock:
226235
def to_dataframe(self) -> pd.DataFrame:
227236
"""
228237
Converts the EventBlock into a DataFrame with each row being an event instance
238+
239+
Args:
240+
None
241+
242+
Returns:
243+
A Pandas DataFrame containing the data of each Event instance in this EventBlock.
229244
"""
245+
230246
# TODO: push row generation down to Event
231247
data = {
232248
"event_block_name": [self.name] * len(self.events),
@@ -320,11 +336,11 @@ def _gen_resolve_debug_handles(
320336
"""
321337
for event in self.events:
322338
# Check if instruction_id is present in the event
323-
if event.instruction_id is None:
339+
if event._instruction_id is None:
324340
continue
325341

326342
# Check for the instruction_id in handle map
327-
if (instruction_id := str(event.instruction_id)) not in handle_map:
343+
if (instruction_id := str(event._instruction_id)) not in handle_map:
328344
continue
329345

330346
# For non-delegated event, handles are found in handle_map
@@ -339,7 +355,7 @@ def _gen_resolve_debug_handles(
339355
):
340356
event.debug_handles = handle_map[instruction_id]
341357
log.warning(
342-
f" No delegate mapping found for delegate with instruction id {event.instruction_id}"
358+
f" No delegate mapping found for delegate with instruction id {event._instruction_id}"
343359
)
344360
continue
345361

@@ -376,14 +392,18 @@ def __init__(
376392
etrecord_path: Optional[str] = None,
377393
etdump_scale: int = 1000,
378394
) -> None:
379-
"""
380-
Create an inspector instance from the provided ETDump/ETRecord
395+
r"""
396+
Initialize an `Inspector` instance with the underlying `EventBlock`\ s populated with data from the provided ETDump path
397+
and optional ETRecord path.
381398
382399
Args:
383400
etdump_path: Path to the ETDump file.
384-
etrecord_path: Path to the ETRecord file.
401+
etrecord_path: Optional path to the ETRecord file.
385402
etdump_scale: Inverse Scale Factor used to cast the timestamps in ETDump
386403
defaults to milli (1000ms = 1s).
404+
405+
Returns:
406+
None
387407
"""
388408

389409
self._etrecord = (
@@ -422,7 +442,13 @@ def __init__(
422442

423443
def print_data_tabular(self) -> None:
424444
"""
425-
Prints the underlying EventBlocks (essentially all the performance data)
445+
Displays the underlying EventBlocks in a structured tabular format, with each row representing an Event.
446+
447+
Args:
448+
None
449+
450+
Returns:
451+
None
426452
"""
427453

428454
def style_text_size(val, size=12):
@@ -447,7 +473,17 @@ def style_text_size(val, size=12):
447473
print(tabulate(filtered_df, headers="keys", tablefmt="fancy_grid"))
448474

449475
# TODO: write unit test
450-
def find_total_for_module(self, module_name: str):
476+
def find_total_for_module(self, module_name: str) -> float:
477+
"""
478+
Returns the total average compute time of all operators within the specified module.
479+
480+
Args:
481+
module_name: Name of the module to be aggregated against.
482+
483+
Returns:
484+
Sum of the average compute time (in seconds) of all operators within the module with "module_name".
485+
"""
486+
451487
total = 0.0
452488
for block in self.event_blocks:
453489
for event in block.events:
@@ -481,10 +517,13 @@ def get_exported_program(
481517
self, graph: Optional[str] = None
482518
) -> Optional[ExportedProgram]:
483519
"""
484-
Access helper for ETRecord, defaults to returning Edge Dialect Program
520+
Access helper for ETRecord, defaults to returning the Edge Dialect program.
485521
486522
Args:
487-
graph: Name of the graph to access. If None, returns the Edge Dialect Program.
523+
graph: Optional name of the graph to access. If None, returns the Edge Dialect program.
524+
525+
Returns:
526+
The ExportedProgram object of "graph".
488527
"""
489528
if self._etrecord is None:
490529
log.warning(

sdk/inspector/tests/event_blocks_test.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,13 @@ def _test_profile_event_generation(
192192

193193
is_delegated = delegate_debug_id is not None
194194
expected_event = Event(
195-
str(delegate_debug_id) if is_delegated else name,
196-
PerfData([float(duration) / scale_factor for duration in durations]),
197-
instruction_id=signature.instruction_id,
195+
name=str(delegate_debug_id) if is_delegated else name,
196+
perf_data=PerfData(
197+
[float(duration) / scale_factor for duration in durations]
198+
),
198199
delegate_debug_identifier=delegate_debug_id,
199200
is_delegated_op=is_delegated,
201+
_instruction_id=signature.instruction_id,
200202
)
201203
self.assertEqual(event, expected_event)
202204

@@ -283,12 +285,12 @@ def _gen_event_helper(events: List[ProfileEvent]) -> Event:
283285
# Verify Results
284286
for event in event_block.events:
285287
# To satisfy type checker
286-
assert event.instruction_id is not None
288+
assert event._instruction_id is not None
287289
if (
288290
delegate_debug_identifier := event.delegate_debug_identifier
289291
) is not None:
290292
# Delegated
291-
metadata = delegate_map[str(event.instruction_id)]
293+
metadata = delegate_map[str(event._instruction_id)]
292294
self.assertEqual(event.delegate_backend_name, metadata["name"])
293295
self.assertEqual(
294296
event.debug_handles,
@@ -297,5 +299,5 @@ def _gen_event_helper(events: List[ProfileEvent]) -> Event:
297299
else:
298300
# Non Delegated
299301
self.assertEqual(
300-
event.debug_handles, handle_map[str(event.instruction_id)]
302+
event.debug_handles, handle_map[str(event._instruction_id)]
301303
)

0 commit comments

Comments
 (0)