Skip to content

Commit 2d3685f

Browse files
Olivia-liufacebook-github-bot
authored andcommitted
Introduce a new interface in lib.py and the ETInspector class (#111)
Summary: Pull Request resolved: #111 ## About this stack To upgrade the SDK debugger so that it offers not only the CLI experience, but also public APIs that return DataFrames containing model architecture info and profiling stats info. Once this tool is in a usable state, we can migrate the new logic to the internal flow (executorch/sdk/fb/lib.py) ## About this diff Define the skeleton of the ETInspector class (including all the high-pri APIs). In lib.py, defines the APIs that initialize an ETInspector. Note that this diff basically turns the CLI useless temporarily. No one is using the CLI rn so it should be fine. ## Next Define the DataFrame schemas Reviewed By: Jack-Khuu Differential Revision: D48456830 fbshipit-source-id: 7ac6327da3ab07e273ca14667a5e6fadd3407ff6
1 parent 85c2b4c commit 2d3685f

File tree

4 files changed

+155
-2
lines changed

4 files changed

+155
-2
lines changed

sdk/TARGETS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ python_library(
1212
deps = [
1313
"//executorch/sdk/edir:et_schema",
1414
"//executorch/sdk/etdb:etdb",
15+
"//executorch/sdk/etdb:inspector",
1516
"//executorch/sdk/etrecord:etrecord",
1617
],
1718
)
@@ -23,6 +24,7 @@ python_binary(
2324
deps = [
2425
"//executorch/sdk/edir:et_schema",
2526
"//executorch/sdk/etdb:etdb",
27+
"//executorch/sdk/etdb:inspector",
2628
"//executorch/sdk/etrecord:etrecord",
2729
],
2830
)

sdk/etdb/TARGETS

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,14 @@ python_library(
2525
"//executorch/sdk/edir:et_schema",
2626
],
2727
)
28+
29+
python_library(
30+
name = "inspector",
31+
srcs = [
32+
"inspector.py",
33+
],
34+
deps = [
35+
"fbsource//third-party/pypi/pandas:pandas",
36+
"//executorch/sdk/edir:et_schema",
37+
],
38+
)

sdk/etdb/inspector.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
import os
8+
from typing import Mapping, Optional
9+
10+
from executorch.sdk.edir.et_schema import InferenceRun, OperatorGraphWithStats
11+
from pandas import DataFrame
12+
13+
14+
class Inspector:
15+
16+
"""
17+
APIs for examining model architecture and performance stats
18+
"""
19+
20+
def __init__(
21+
self,
22+
op_graph_dict: Mapping[str, OperatorGraphWithStats],
23+
show_stack_trace: Optional[bool] = False,
24+
verbose: Optional[bool] = False,
25+
) -> None:
26+
"""
27+
Constructor that returns a Debugger instance from a dict of OperatorGraph instances and some optional parameters
28+
"""
29+
# Save the parameters into class members
30+
self.op_graph_dict = op_graph_dict
31+
self.show_stack_trace = show_stack_trace
32+
self.verbose = verbose
33+
34+
# Construct the initial tables and save in class members
35+
self.architecture_table = self._gen_architecture_table()
36+
self.high_level_profile_info_table = self._gen_high_level_profile_info_table()
37+
38+
def attach_etdump(self, etdump_path: str) -> None:
39+
"""
40+
API that attaches ETDump to this inspector instance
41+
"""
42+
op_graph = self.op_graph_dict["et_dialect_graph_module/forward"]
43+
44+
if os.path.exists(etdump_path):
45+
op_graph.attach_metadata(
46+
inference_run=InferenceRun.extract_runs_from_path(
47+
file_path=etdump_path
48+
)[0]
49+
)
50+
else:
51+
raise Exception("Invalid ET Dump path")
52+
53+
def get_high_level_profile_info_table(self) -> DataFrame:
54+
"""
55+
API that returns the high level profile information table from class member
56+
"""
57+
return self.high_level_profile_info_table
58+
59+
def get_architecture_table(self) -> DataFrame:
60+
"""
61+
API that returns the architecture table from class member, filtered by user options (e.g. self.show_stack_trace)
62+
"""
63+
# TODO: filter based on user options (self.show_stack_trace) before return
64+
return self.architecture_table
65+
66+
def cli_flow(self):
67+
"""
68+
API that enters the CLI debugging flow
69+
"""
70+
print("Entering the CLI debugging flow...")
71+
72+
print("High level profile information table:")
73+
print(self.get_high_level_profile_info_table())
74+
print("Architecture table:")
75+
print(self.get_architecture_table())
76+
77+
# TODO: Take user commands, process by calling other APIs in the Inspector class
78+
79+
def select_by_instance_id(self, instance_id: str) -> DataFrame:
80+
"""
81+
API that returns a DataFrame containing information for a specific instance id
82+
"""
83+
# TODO: filter the architecture table by the instance id before return
84+
return self.architecture_table
85+
86+
def select_by_instance_type(self, instance_type: str) -> DataFrame:
87+
"""
88+
API that returns a DataFrame containing instances with the given instance type
89+
"""
90+
# TODO: filter the architecture table by the instance type before return
91+
return self.architecture_table
92+
93+
def _gen_high_level_profile_info_table(self) -> DataFrame:
94+
"""
95+
Private helper function that generates the high level profile information table
96+
"""
97+
# TODO: implement
98+
pass
99+
100+
def _gen_architecture_table(self) -> DataFrame:
101+
"""
102+
Private helper function that generates the architecture table
103+
"""
104+
# TODO: implement
105+
pass

sdk/lib.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
import argparse
88
import asyncio
99
import os
10-
from typing import Mapping, Optional
10+
from typing import Mapping, Optional, Union
1111

1212
from executorch.sdk.edir.et_schema import (
1313
FXOperatorGraph,
1414
InferenceRun,
1515
OperatorGraphWithStats,
1616
)
1717
from executorch.sdk.etdb.etdb import debug_graphs
18+
from executorch.sdk.etdb.inspector import Inspector
1819
from executorch.sdk.etrecord import ETRecord, parse_etrecord
1920

2021
"""
@@ -86,6 +87,30 @@ def debug_etrecord_path(
8687
debug_etrecord(parse_etrecord(etrecord_path), et_dump_path, verbose)
8788

8889

90+
def gen_inspector_from_etrecord(
91+
etrecord: Union[str, ETRecord],
92+
etdump_path: Optional[str] = None,
93+
show_stack_trace: Optional[bool] = False,
94+
verbose: Optional[bool] = False,
95+
) -> Inspector:
96+
"""
97+
API that creates an Inspector instance based on a file path to an ETRecord instance
98+
or an ETRecord instance and optional parameters including a file path to an ETDump
99+
"""
100+
if isinstance(etrecord, str):
101+
etrecord = parse_etrecord(etrecord_path=str(etrecord))
102+
103+
op_graph_dict: Mapping[str, OperatorGraphWithStats] = _gen_graphs_from_etrecord(
104+
etrecord=etrecord
105+
)
106+
if etdump_path is not None:
107+
_gen_and_attach_metadata(op_graph_dict=op_graph_dict, et_dump_path=etdump_path)
108+
109+
return Inspector(
110+
op_graph_dict=op_graph_dict, show_stack_trace=show_stack_trace, verbose=verbose
111+
)
112+
113+
89114
"""
90115
SDK Binary
91116
"""
@@ -100,6 +125,10 @@ def parse_args():
100125
action="store_true",
101126
help="Whether the terminal should display in verbose mode",
102127
)
128+
parser.add_argument(
129+
"--show_stack_trace",
130+
help="Whether to show stack trace in the output tables",
131+
)
103132
return parser.parse_args()
104133

105134

@@ -110,7 +139,13 @@ async def main() -> int:
110139
Only required argument is an et_record path
111140
"""
112141
args = parse_args()
113-
debug_etrecord_path(args.et_record, args.et_dump, args.verbose)
142+
et_inspector = gen_inspector_from_etrecord(
143+
etrecord=args.et_record,
144+
etdump_path=args.et_dump,
145+
show_stack_trace=args.show_stack_trace,
146+
verbose=args.verbose,
147+
)
148+
et_inspector.cli_flow()
114149
return 0
115150

116151

0 commit comments

Comments
 (0)