Skip to content

Commit 9598e4d

Browse files
Ashwin Rameshdzier
authored andcommitted
Offline mode for analyze and report (#164)
* Offline mode for analyze and report * Review edits * Fixed online mode defaults
1 parent fe8e8cb commit 9598e4d

18 files changed

+500
-296
lines changed

docs/cli.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,18 @@ $ model-analyzer -h
2424
```
2525

2626
Options like `-q`, `--quiet` and `-v`, `--verbose` are global and apply to all
27-
model analyzer subcommands.
27+
model analyzer subcommands.
28+
29+
## Model Analyze Modes
30+
31+
The `-m` or `--mode` flag is global and is accessible to all subcommands. It tells the model analyzer the context
32+
in which it is being run. Currently model analyzer supports 2 modes.
33+
34+
### Online Mode
35+
36+
This is the default mode. When in this mode, Model Analyzer will operate to find the optimal model
37+
configuration for an online inference scenario. In this scenario, Triton server will receive requests
38+
on demand with an expectation that latency will be minimized.
2839

2940
## Model Analyzer Subcommands
3041

model_analyzer/analyzer.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,17 @@ def profile(self, client):
118118
f"Finished profiling. Obtained measurements for models: {profiled_model_list}."
119119
)
120120

121-
def analyze(self):
121+
def analyze(self, mode):
122122
"""
123123
subcommand: ANALYZE
124124
125125
Constructs results from measurements,
126126
sorts them, and dumps them to tables.
127+
128+
Parameters
129+
----------
130+
mode : str
131+
Global mode that the analyzer is running on
127132
"""
128133

129134
if not isinstance(self._config, ConfigCommandAnalyze):
@@ -136,6 +141,7 @@ def analyze(self):
136141
if not gpu_info:
137142
gpu_info = {}
138143
self._report_manager = ReportManager(
144+
mode=mode,
139145
config=self._config,
140146
gpu_info=gpu_info,
141147
result_manager=self._result_manager)
@@ -155,12 +161,17 @@ def analyze(self):
155161
self._result_manager.tabulate_results()
156162
self._result_manager.write_and_export_results()
157163

158-
def report(self):
164+
def report(self, mode):
159165
"""
160166
Subcommand: REPORT
161167
162168
Generates detailed information on
163169
one or more model configs
170+
171+
Parameters
172+
----------
173+
mode : str
174+
Global mode that the analyzer is running on
164175
"""
165176

166177
if not isinstance(self._config, ConfigCommandReport):
@@ -173,6 +184,7 @@ def report(self):
173184
if not gpu_info:
174185
gpu_info = {}
175186
self._report_manager = ReportManager(
187+
mode=mode,
176188
config=self._config,
177189
result_manager=self._result_manager,
178190
gpu_info=gpu_info)

model_analyzer/cli/cli.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import sys
1615
import logging
1716
import argparse
1817
from argparse import ArgumentParser
@@ -24,7 +23,6 @@ class CLI:
2423
"""
2524
CLI class to parse the commandline arguments
2625
"""
27-
2826
def __init__(self):
2927
self._parser = ArgumentParser()
3028
self._add_global_options()
@@ -36,9 +34,8 @@ def __init__(self):
3634

3735
def _add_global_options(self):
3836
"""
39-
Retrieves the arguments from the command line and loads them into an
40-
ArgumentParser. It will also configure the Model Analyzer config
41-
accordingly.
37+
Adds the Model Analyzer's global options
38+
to the parser
4239
"""
4340

4441
self._parser.add_argument(
@@ -54,6 +51,7 @@ def _add_global_options(self):
5451
self._parser.add_argument('-m',
5552
'--mode',
5653
type=str,
54+
default='online',
5755
choices=['online', 'offline'],
5856
help='Choose a preset configuration mode.')
5957

@@ -100,8 +98,8 @@ def _add_config_arguments(self, subparser, config):
10098
# 'store_true' and 'store_false' does not
10199
# allow 'type' or 'choices' parameters
102100
if 'action' in parser_args and (
103-
parser_args['action'] == 'store_true' or
104-
parser_args['action'] == 'store_false'):
101+
parser_args['action'] == 'store_true'
102+
or parser_args['action'] == 'store_false'):
105103
subparser.add_argument(
106104
*config.flags(),
107105
default=argparse.SUPPRESS,

model_analyzer/config/input/config_command_analyze.py

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
# limitations under the License.
1414

1515
from .config_defaults import \
16-
DEFAULT_ANALYSIS_PLOTS, DEFAULT_CHECKPOINT_DIRECTORY, DEFAULT_EXPORT_PATH, \
16+
DEFAULT_CHECKPOINT_DIRECTORY, DEFAULT_EXPORT_PATH, \
1717
DEFAULT_FILENAME_MODEL_GPU, DEFAULT_FILENAME_MODEL_INFERENCE, \
1818
DEFAULT_FILENAME_SERVER_ONLY, DEFAULT_GPU_OUTPUT_FIELDS, \
1919
DEFAULT_INFERENCE_OUTPUT_FIELDS, DEFAULT_NUM_CONFIGS_PER_MODEL, \
20-
DEFAULT_NUM_TOP_MODEL_CONFIGS, DEFAULT_OBJECTIVES, \
21-
DEFAULT_SERVER_OUTPUT_FIELDS, DEFAULT_SUMMARIZE_FLAG
20+
DEFAULT_NUM_TOP_MODEL_CONFIGS, DEFAULT_OFFLINE_OBJECTIVES, DEFAULT_ONLINE_ANALYSIS_PLOTS, \
21+
DEFAULT_OFFLINE_ANALYSIS_PLOTS, DEFAULT_ONLINE_OBJECTIVES,DEFAULT_SERVER_OUTPUT_FIELDS, DEFAULT_SUMMARIZE_FLAG
2222
from .config_field import ConfigField
2323
from .config_object import ConfigObject
2424
from .config_union import ConfigUnion
@@ -97,7 +97,7 @@ def objective_list_output_mapper(objectives):
9797
ConfigField(
9898
'objectives',
9999
field_type=objectives_scheme,
100-
default_value=DEFAULT_OBJECTIVES,
100+
default_value=DEFAULT_OFFLINE_OBJECTIVES,
101101
description=
102102
'Model Analyzer uses the objectives described here to find the best configuration for each model.'
103103
))
@@ -276,6 +276,13 @@ def _add_shorthand_configs(self):
276276
description=
277277
"Shorthand flag for specifying a maximum latency in ms."))
278278

279+
self._add_config(
280+
ConfigField('min_throughput',
281+
flags=['--min-throughput'],
282+
field_type=ConfigPrimitive(int),
283+
description=
284+
"Shorthand flag for specifying a minimum throughput."))
285+
279286
def _preprocess_and_verify_arguments(self):
280287
"""
281288
Enforces some rules on the config.
@@ -318,11 +325,18 @@ def set_config_values(self, args):
318325
this exception
319326
"""
320327

328+
if args.mode == 'online' and 'latency_budget' not in args:
329+
self._fields['objectives'].set_default_value(
330+
DEFAULT_ONLINE_OBJECTIVES)
331+
321332
super().set_config_values(args)
322333

323334
# Add plot configs and after config parse. User should not be able to edit these plots
324335
self._add_plot_configs()
325-
self._fields['plots'].set_value(DEFAULT_ANALYSIS_PLOTS)
336+
if args.mode == 'online':
337+
self._fields['plots'].set_value(DEFAULT_ONLINE_ANALYSIS_PLOTS)
338+
elif args.mode == 'offline':
339+
self._fields['plots'].set_value(DEFAULT_OFFLINE_ANALYSIS_PLOTS)
326340

327341
def _add_plot_configs(self):
328342
"""
@@ -369,6 +383,18 @@ def _autofill_values(self):
369383
'max': self.latency_budget
370384
}})
371385

386+
# Set global constraints if latency budget is specified
387+
if self.min_throughput:
388+
if self.constraints:
389+
constraints = self.constraints
390+
constraints['perf_throughput'] = {'min': self.min_throughput}
391+
self._fields['constraints'].set_value(constraints)
392+
else:
393+
self._fields['constraints'].set_value(
394+
{'perf_throughput': {
395+
'min': self.min_throughput
396+
}})
397+
372398
new_analysis_models = {}
373399
for model in self.analysis_models:
374400
new_model = {}
@@ -397,5 +423,17 @@ def _autofill_values(self):
397423
'max': self.latency_budget
398424
}
399425
}
426+
427+
if self.min_throughput:
428+
if 'constraints' in new_model:
429+
new_model['constraints']['perf_throughput'] = {
430+
'min': self.min_throughput
431+
}
432+
else:
433+
new_model['constraints'] = {
434+
'perf_throughput': {
435+
'min': self.min_throughput
436+
}
437+
}
400438
new_analysis_models[model.model_name()] = new_model
401439
self._fields['analysis_models'].set_value(new_analysis_models)

model_analyzer/config/input/config_command_profile.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
from .config_defaults import \
3030
DEFAULT_BATCH_SIZES, DEFAULT_CHECKPOINT_DIRECTORY, \
3131
DEFAULT_CLIENT_PROTOCOL, DEFAULT_DURATION_SECONDS, \
32-
DEFAULT_GPUS, DEFAULT_LOG_LEVEL, DEFAULT_MAX_RETRIES, \
33-
DEFAULT_MONITORING_INTERVAL, DEFAULT_OBJECTIVES, \
32+
DEFAULT_GPUS, DEFAULT_MAX_RETRIES, \
33+
DEFAULT_MONITORING_INTERVAL, DEFAULT_OFFLINE_OBJECTIVES, \
3434
DEFAULT_OUTPUT_MODEL_REPOSITORY, DEFAULT_OVERRIDE_OUTPUT_REPOSITORY_FLAG, \
3535
DEFAULT_PERF_ANALYZER_CPU_UTIL, DEFAULT_PERF_ANALYZER_PATH, DEFAULT_PERF_ANALYZER_TIMEOUT, \
3636
DEFAULT_PERF_OUTPUT_FLAG, DEFAULT_RUN_CONFIG_MAX_CONCURRENCY, \
@@ -287,7 +287,7 @@ def objective_list_output_mapper(objectives):
287287
ConfigField(
288288
'objectives',
289289
field_type=objectives_scheme,
290-
default_value=DEFAULT_OBJECTIVES,
290+
default_value=DEFAULT_OFFLINE_OBJECTIVES,
291291
description=
292292
'Model Analyzer uses the objectives described here to find the best configuration for each model.'
293293
))

model_analyzer/config/input/config_command_report.py

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
from .config_list_generic import ConfigListGeneric
2121
from .config_list_string import ConfigListString
2222
from .config_defaults import \
23-
DEFAULT_CHECKPOINT_DIRECTORY, DEFAULT_EXPORT_PATH, DEFAULT_REPORT_FORMAT, DEFAULT_REPORT_PLOTS
23+
DEFAULT_CHECKPOINT_DIRECTORY, DEFAULT_EXPORT_PATH, \
24+
DEFAULT_OFFLINE_REPORT_PLOTS, DEFAULT_ONLINE_REPORT_PLOTS, DEFAULT_REPORT_FORMAT
2425
from .config_field import ConfigField
2526
from .config_primitive import ConfigPrimitive
2627
from .config_command import ConfigCommand
@@ -36,7 +37,6 @@ class ConfigCommandReport(ConfigCommand):
3637
"""
3738
Model Analyzer config object.
3839
"""
39-
4040
def _fill_config(self):
4141
"""
4242
Builder function makes calls to add config to
@@ -59,21 +59,22 @@ def _fill_config(self):
5959
"Full path to directory to which to read and write checkpoints and profile data."
6060
))
6161
self._add_config(
62-
ConfigField('export_path',
63-
flags=['--export-path', '-e'],
64-
default_value=DEFAULT_EXPORT_PATH,
65-
field_type=ConfigPrimitive(str),
66-
description=
67-
"Full path to directory in which to store the results"))
62+
ConfigField(
63+
'export_path',
64+
flags=['--export-path', '-e'],
65+
default_value=DEFAULT_EXPORT_PATH,
66+
field_type=ConfigPrimitive(str),
67+
description=
68+
"Full path to directory in which to store the results"))
6869
plots_scheme = ConfigObject(schema={
6970
'*':
70-
ConfigObject(
71-
schema={
72-
'title': ConfigPrimitive(type_=str),
73-
'x_axis': ConfigPrimitive(type_=str),
74-
'y_axis': ConfigPrimitive(type_=str),
75-
'monotonic': ConfigPrimitive(type_=bool)
76-
})
71+
ConfigObject(
72+
schema={
73+
'title': ConfigPrimitive(type_=str),
74+
'x_axis': ConfigPrimitive(type_=str),
75+
'y_axis': ConfigPrimitive(type_=str),
76+
'monotonic': ConfigPrimitive(type_=bool)
77+
})
7778
},
7879
output_mapper=ConfigPlot.from_object)
7980
self._add_config(
@@ -84,7 +85,7 @@ def _fill_config(self):
8485
ConfigListGeneric(type_=plots_scheme,
8586
output_mapper=ConfigPlot.from_list)
8687
]),
87-
default_value=DEFAULT_REPORT_PLOTS,
88+
default_value=DEFAULT_ONLINE_REPORT_PLOTS,
8889
description=
8990
'Model analyzer uses the information in this section to construct plots of the results.'
9091
))
@@ -131,6 +132,33 @@ def _fill_config(self):
131132
]),
132133
description='Output file format for detailed report.'))
133134

135+
def set_config_values(self, args):
136+
"""
137+
Set the config values. This function sets all the values for the
138+
config. CLI arguments have the highest priority, then YAML config
139+
values and then default values.
140+
141+
Parameters
142+
----------
143+
args : argparse.Namespace
144+
Parsed arguments from the CLI
145+
146+
Raises
147+
------
148+
TritonModelAnalyzerException
149+
If the required fields are not specified, it will raise
150+
this exception
151+
"""
152+
153+
if args.mode == 'online':
154+
self._fields['plots'].set_default_value(
155+
DEFAULT_ONLINE_REPORT_PLOTS)
156+
elif args.mode == 'offline':
157+
self._fields['plots'].set_default_value(
158+
DEFAULT_OFFLINE_REPORT_PLOTS)
159+
160+
super().set_config_values(args)
161+
134162
def _preprocess_and_verify_arguments(self):
135163
"""
136164
Enforces some rules on the config.
@@ -167,7 +195,8 @@ def _autofill_values(self):
167195
'x_axis': plot.x_axis(),
168196
'y_axis': plot.y_axis(),
169197
'monotonic': plot.monotonic()
170-
} for plot in self.plots
198+
}
199+
for plot in self.plots
171200
}
172201
else:
173202
new_report_model_config['plots'] = {
@@ -176,10 +205,12 @@ def _autofill_values(self):
176205
'x_axis': plot.x_axis(),
177206
'y_axis': plot.y_axis(),
178207
'monotonic': plot.monotonic()
179-
} for plot in model.plots()
208+
}
209+
for plot in model.plots()
180210
}
181211

182212
new_report_model_configs[
183213
model.model_config_name()] = new_report_model_config
184214

185-
self._fields['report_model_configs'].set_value(new_report_model_configs)
215+
self._fields['report_model_configs'].set_value(
216+
new_report_model_configs)

0 commit comments

Comments
 (0)