triton-model-analyzer 1.48.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. model_analyzer/__init__.py +15 -0
  2. model_analyzer/analyzer.py +448 -0
  3. model_analyzer/cli/__init__.py +15 -0
  4. model_analyzer/cli/cli.py +193 -0
  5. model_analyzer/config/__init__.py +15 -0
  6. model_analyzer/config/generate/__init__.py +15 -0
  7. model_analyzer/config/generate/automatic_model_config_generator.py +164 -0
  8. model_analyzer/config/generate/base_model_config_generator.py +352 -0
  9. model_analyzer/config/generate/brute_plus_binary_parameter_search_run_config_generator.py +164 -0
  10. model_analyzer/config/generate/brute_run_config_generator.py +154 -0
  11. model_analyzer/config/generate/concurrency_sweeper.py +75 -0
  12. model_analyzer/config/generate/config_generator_interface.py +52 -0
  13. model_analyzer/config/generate/coordinate.py +143 -0
  14. model_analyzer/config/generate/coordinate_data.py +86 -0
  15. model_analyzer/config/generate/generator_utils.py +116 -0
  16. model_analyzer/config/generate/manual_model_config_generator.py +187 -0
  17. model_analyzer/config/generate/model_config_generator_factory.py +92 -0
  18. model_analyzer/config/generate/model_profile_spec.py +74 -0
  19. model_analyzer/config/generate/model_run_config_generator.py +154 -0
  20. model_analyzer/config/generate/model_variant_name_manager.py +150 -0
  21. model_analyzer/config/generate/neighborhood.py +536 -0
  22. model_analyzer/config/generate/optuna_plus_concurrency_sweep_run_config_generator.py +141 -0
  23. model_analyzer/config/generate/optuna_run_config_generator.py +838 -0
  24. model_analyzer/config/generate/perf_analyzer_config_generator.py +312 -0
  25. model_analyzer/config/generate/quick_plus_concurrency_sweep_run_config_generator.py +130 -0
  26. model_analyzer/config/generate/quick_run_config_generator.py +753 -0
  27. model_analyzer/config/generate/run_config_generator_factory.py +329 -0
  28. model_analyzer/config/generate/search_config.py +112 -0
  29. model_analyzer/config/generate/search_dimension.py +73 -0
  30. model_analyzer/config/generate/search_dimensions.py +85 -0
  31. model_analyzer/config/generate/search_parameter.py +49 -0
  32. model_analyzer/config/generate/search_parameters.py +388 -0
  33. model_analyzer/config/input/__init__.py +15 -0
  34. model_analyzer/config/input/config_command.py +483 -0
  35. model_analyzer/config/input/config_command_profile.py +1747 -0
  36. model_analyzer/config/input/config_command_report.py +267 -0
  37. model_analyzer/config/input/config_defaults.py +236 -0
  38. model_analyzer/config/input/config_enum.py +83 -0
  39. model_analyzer/config/input/config_field.py +216 -0
  40. model_analyzer/config/input/config_list_generic.py +112 -0
  41. model_analyzer/config/input/config_list_numeric.py +151 -0
  42. model_analyzer/config/input/config_list_string.py +111 -0
  43. model_analyzer/config/input/config_none.py +71 -0
  44. model_analyzer/config/input/config_object.py +129 -0
  45. model_analyzer/config/input/config_primitive.py +81 -0
  46. model_analyzer/config/input/config_status.py +75 -0
  47. model_analyzer/config/input/config_sweep.py +83 -0
  48. model_analyzer/config/input/config_union.py +113 -0
  49. model_analyzer/config/input/config_utils.py +128 -0
  50. model_analyzer/config/input/config_value.py +243 -0
  51. model_analyzer/config/input/objects/__init__.py +15 -0
  52. model_analyzer/config/input/objects/config_model_profile_spec.py +325 -0
  53. model_analyzer/config/input/objects/config_model_report_spec.py +173 -0
  54. model_analyzer/config/input/objects/config_plot.py +198 -0
  55. model_analyzer/config/input/objects/config_protobuf_utils.py +101 -0
  56. model_analyzer/config/input/yaml_config_validator.py +82 -0
  57. model_analyzer/config/run/__init__.py +15 -0
  58. model_analyzer/config/run/model_run_config.py +313 -0
  59. model_analyzer/config/run/run_config.py +168 -0
  60. model_analyzer/constants.py +76 -0
  61. model_analyzer/device/__init__.py +15 -0
  62. model_analyzer/device/device.py +24 -0
  63. model_analyzer/device/gpu_device.py +87 -0
  64. model_analyzer/device/gpu_device_factory.py +248 -0
  65. model_analyzer/entrypoint.py +307 -0
  66. model_analyzer/log_formatter.py +65 -0
  67. model_analyzer/model_analyzer_exceptions.py +24 -0
  68. model_analyzer/model_manager.py +255 -0
  69. model_analyzer/monitor/__init__.py +15 -0
  70. model_analyzer/monitor/cpu_monitor.py +69 -0
  71. model_analyzer/monitor/dcgm/DcgmDiag.py +191 -0
  72. model_analyzer/monitor/dcgm/DcgmFieldGroup.py +83 -0
  73. model_analyzer/monitor/dcgm/DcgmGroup.py +815 -0
  74. model_analyzer/monitor/dcgm/DcgmHandle.py +141 -0
  75. model_analyzer/monitor/dcgm/DcgmJsonReader.py +69 -0
  76. model_analyzer/monitor/dcgm/DcgmReader.py +623 -0
  77. model_analyzer/monitor/dcgm/DcgmStatus.py +57 -0
  78. model_analyzer/monitor/dcgm/DcgmSystem.py +412 -0
  79. model_analyzer/monitor/dcgm/__init__.py +15 -0
  80. model_analyzer/monitor/dcgm/common/__init__.py +13 -0
  81. model_analyzer/monitor/dcgm/common/dcgm_client_cli_parser.py +194 -0
  82. model_analyzer/monitor/dcgm/common/dcgm_client_main.py +86 -0
  83. model_analyzer/monitor/dcgm/dcgm_agent.py +887 -0
  84. model_analyzer/monitor/dcgm/dcgm_collectd_plugin.py +369 -0
  85. model_analyzer/monitor/dcgm/dcgm_errors.py +395 -0
  86. model_analyzer/monitor/dcgm/dcgm_field_helpers.py +546 -0
  87. model_analyzer/monitor/dcgm/dcgm_fields.py +815 -0
  88. model_analyzer/monitor/dcgm/dcgm_fields_collectd.py +671 -0
  89. model_analyzer/monitor/dcgm/dcgm_fields_internal.py +29 -0
  90. model_analyzer/monitor/dcgm/dcgm_fluentd.py +45 -0
  91. model_analyzer/monitor/dcgm/dcgm_monitor.py +138 -0
  92. model_analyzer/monitor/dcgm/dcgm_prometheus.py +326 -0
  93. model_analyzer/monitor/dcgm/dcgm_structs.py +2357 -0
  94. model_analyzer/monitor/dcgm/dcgm_telegraf.py +65 -0
  95. model_analyzer/monitor/dcgm/dcgm_value.py +151 -0
  96. model_analyzer/monitor/dcgm/dcgmvalue.py +155 -0
  97. model_analyzer/monitor/dcgm/denylist_recommendations.py +573 -0
  98. model_analyzer/monitor/dcgm/pydcgm.py +47 -0
  99. model_analyzer/monitor/monitor.py +143 -0
  100. model_analyzer/monitor/remote_monitor.py +137 -0
  101. model_analyzer/output/__init__.py +15 -0
  102. model_analyzer/output/file_writer.py +63 -0
  103. model_analyzer/output/output_writer.py +42 -0
  104. model_analyzer/perf_analyzer/__init__.py +15 -0
  105. model_analyzer/perf_analyzer/genai_perf_config.py +206 -0
  106. model_analyzer/perf_analyzer/perf_analyzer.py +882 -0
  107. model_analyzer/perf_analyzer/perf_config.py +479 -0
  108. model_analyzer/plots/__init__.py +15 -0
  109. model_analyzer/plots/detailed_plot.py +266 -0
  110. model_analyzer/plots/plot_manager.py +224 -0
  111. model_analyzer/plots/simple_plot.py +213 -0
  112. model_analyzer/record/__init__.py +15 -0
  113. model_analyzer/record/gpu_record.py +68 -0
  114. model_analyzer/record/metrics_manager.py +887 -0
  115. model_analyzer/record/record.py +280 -0
  116. model_analyzer/record/record_aggregator.py +256 -0
  117. model_analyzer/record/types/__init__.py +15 -0
  118. model_analyzer/record/types/cpu_available_ram.py +93 -0
  119. model_analyzer/record/types/cpu_used_ram.py +93 -0
  120. model_analyzer/record/types/gpu_free_memory.py +96 -0
  121. model_analyzer/record/types/gpu_power_usage.py +107 -0
  122. model_analyzer/record/types/gpu_total_memory.py +96 -0
  123. model_analyzer/record/types/gpu_used_memory.py +96 -0
  124. model_analyzer/record/types/gpu_utilization.py +108 -0
  125. model_analyzer/record/types/inter_token_latency_avg.py +60 -0
  126. model_analyzer/record/types/inter_token_latency_base.py +74 -0
  127. model_analyzer/record/types/inter_token_latency_max.py +60 -0
  128. model_analyzer/record/types/inter_token_latency_min.py +60 -0
  129. model_analyzer/record/types/inter_token_latency_p25.py +60 -0
  130. model_analyzer/record/types/inter_token_latency_p50.py +60 -0
  131. model_analyzer/record/types/inter_token_latency_p75.py +60 -0
  132. model_analyzer/record/types/inter_token_latency_p90.py +60 -0
  133. model_analyzer/record/types/inter_token_latency_p95.py +60 -0
  134. model_analyzer/record/types/inter_token_latency_p99.py +60 -0
  135. model_analyzer/record/types/output_token_throughput.py +105 -0
  136. model_analyzer/record/types/perf_client_response_wait.py +97 -0
  137. model_analyzer/record/types/perf_client_send_recv.py +97 -0
  138. model_analyzer/record/types/perf_latency.py +111 -0
  139. model_analyzer/record/types/perf_latency_avg.py +60 -0
  140. model_analyzer/record/types/perf_latency_base.py +74 -0
  141. model_analyzer/record/types/perf_latency_p90.py +60 -0
  142. model_analyzer/record/types/perf_latency_p95.py +60 -0
  143. model_analyzer/record/types/perf_latency_p99.py +60 -0
  144. model_analyzer/record/types/perf_server_compute_infer.py +97 -0
  145. model_analyzer/record/types/perf_server_compute_input.py +97 -0
  146. model_analyzer/record/types/perf_server_compute_output.py +97 -0
  147. model_analyzer/record/types/perf_server_queue.py +97 -0
  148. model_analyzer/record/types/perf_throughput.py +105 -0
  149. model_analyzer/record/types/time_to_first_token_avg.py +60 -0
  150. model_analyzer/record/types/time_to_first_token_base.py +74 -0
  151. model_analyzer/record/types/time_to_first_token_max.py +60 -0
  152. model_analyzer/record/types/time_to_first_token_min.py +60 -0
  153. model_analyzer/record/types/time_to_first_token_p25.py +60 -0
  154. model_analyzer/record/types/time_to_first_token_p50.py +60 -0
  155. model_analyzer/record/types/time_to_first_token_p75.py +60 -0
  156. model_analyzer/record/types/time_to_first_token_p90.py +60 -0
  157. model_analyzer/record/types/time_to_first_token_p95.py +60 -0
  158. model_analyzer/record/types/time_to_first_token_p99.py +60 -0
  159. model_analyzer/reports/__init__.py +15 -0
  160. model_analyzer/reports/html_report.py +195 -0
  161. model_analyzer/reports/pdf_report.py +50 -0
  162. model_analyzer/reports/report.py +86 -0
  163. model_analyzer/reports/report_factory.py +62 -0
  164. model_analyzer/reports/report_manager.py +1376 -0
  165. model_analyzer/reports/report_utils.py +42 -0
  166. model_analyzer/result/__init__.py +15 -0
  167. model_analyzer/result/constraint_manager.py +150 -0
  168. model_analyzer/result/model_config_measurement.py +354 -0
  169. model_analyzer/result/model_constraints.py +105 -0
  170. model_analyzer/result/parameter_search.py +246 -0
  171. model_analyzer/result/result_manager.py +430 -0
  172. model_analyzer/result/result_statistics.py +159 -0
  173. model_analyzer/result/result_table.py +217 -0
  174. model_analyzer/result/result_table_manager.py +646 -0
  175. model_analyzer/result/result_utils.py +42 -0
  176. model_analyzer/result/results.py +277 -0
  177. model_analyzer/result/run_config_measurement.py +658 -0
  178. model_analyzer/result/run_config_result.py +210 -0
  179. model_analyzer/result/run_config_result_comparator.py +110 -0
  180. model_analyzer/result/sorted_results.py +151 -0
  181. model_analyzer/state/__init__.py +15 -0
  182. model_analyzer/state/analyzer_state.py +76 -0
  183. model_analyzer/state/analyzer_state_manager.py +215 -0
  184. model_analyzer/triton/__init__.py +15 -0
  185. model_analyzer/triton/client/__init__.py +15 -0
  186. model_analyzer/triton/client/client.py +234 -0
  187. model_analyzer/triton/client/client_factory.py +57 -0
  188. model_analyzer/triton/client/grpc_client.py +104 -0
  189. model_analyzer/triton/client/http_client.py +107 -0
  190. model_analyzer/triton/model/__init__.py +15 -0
  191. model_analyzer/triton/model/model_config.py +556 -0
  192. model_analyzer/triton/model/model_config_variant.py +29 -0
  193. model_analyzer/triton/server/__init__.py +15 -0
  194. model_analyzer/triton/server/server.py +76 -0
  195. model_analyzer/triton/server/server_config.py +269 -0
  196. model_analyzer/triton/server/server_docker.py +229 -0
  197. model_analyzer/triton/server/server_factory.py +306 -0
  198. model_analyzer/triton/server/server_local.py +158 -0
  199. triton_model_analyzer-1.48.0.dist-info/METADATA +52 -0
  200. triton_model_analyzer-1.48.0.dist-info/RECORD +204 -0
  201. triton_model_analyzer-1.48.0.dist-info/WHEEL +5 -0
  202. triton_model_analyzer-1.48.0.dist-info/entry_points.txt +2 -0
  203. triton_model_analyzer-1.48.0.dist-info/licenses/LICENSE +67 -0
  204. triton_model_analyzer-1.48.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ def truncate_model_config_name(model_config_name):
19
+ """
20
+ Truncates the model configuration name if its length exceeds the threshold length.
21
+ ex: long_model_name_config_4 --> long_mod..._config_4
22
+ Parameters
23
+ ----------
24
+ model_config_name: string
25
+ Returns
26
+ -------
27
+ string
28
+ The truncated model configuration name,
29
+ or the original name if it is shorter than the threshold length.
30
+ """
31
+ max_model_config_name_len = 35
32
+
33
+ if len(model_config_name) > max_model_config_name_len:
34
+ config_name = model_config_name[model_config_name.rfind("config_") :]
35
+
36
+ return (
37
+ model_config_name[: (max_model_config_name_len - len(config_name) - 3)]
38
+ + "..."
39
+ + config_name
40
+ )
41
+
42
+ return model_config_name
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ from typing import TYPE_CHECKING, Dict, Union
18
+
19
+ from model_analyzer.record.record import Record
20
+
21
+ if TYPE_CHECKING:
22
+ from model_analyzer.result.run_config_measurement import RunConfigMeasurement
23
+
24
+ from model_analyzer.config.input.config_command_profile import ConfigCommandProfile
25
+ from model_analyzer.config.input.config_command_report import ConfigCommandReport
26
+ from model_analyzer.constants import GLOBAL_CONSTRAINTS_KEY
27
+ from model_analyzer.result.model_constraints import ModelConstraints
28
+
29
+
30
+ class ConstraintManager:
31
+ """
32
+ Handles processing and applying
33
+ constraints on a given measurements
34
+
35
+ Parameters
36
+ ----------
37
+ config: ConfigCommandProfile or ConfigCommandReport
38
+ """
39
+
40
+ def __init__(
41
+ self, config: Union[ConfigCommandProfile, ConfigCommandReport]
42
+ ) -> None:
43
+ self._constraints = {}
44
+
45
+ if config:
46
+ # Model constraints
47
+ if "profile_models" in config.get_config():
48
+ for model in config.profile_models:
49
+ self._constraints[model.model_name()] = model.constraints()
50
+
51
+ # Global constraints
52
+ if "constraints" in config.get_all_config():
53
+ self._constraints[GLOBAL_CONSTRAINTS_KEY] = ModelConstraints(
54
+ config.get_all_config()["constraints"]
55
+ )
56
+
57
+ def get_constraints_for_all_models(self):
58
+ """
59
+ Returns
60
+ -------
61
+ dict
62
+ keys are model names, and values are ModelConstraints objects
63
+ """
64
+
65
+ return self._constraints
66
+
67
+ def satisfies_constraints(
68
+ self, run_config_measurement: "RunConfigMeasurement"
69
+ ) -> bool:
70
+ """
71
+ Checks that the measurements, for every model, satisfy
72
+ the provided list of constraints
73
+
74
+ Parameters
75
+ ----------
76
+ run_config_measurement : RunConfigMeasurement
77
+ The measurement to check against the constraints
78
+
79
+ Returns
80
+ -------
81
+ True if measurement passes constraints
82
+ False otherwise
83
+ """
84
+
85
+ if self._constraints:
86
+ for model_name, model_metrics in run_config_measurement.data().items():
87
+ for metric in model_metrics:
88
+ if self._metric_matches_constraint(
89
+ metric, self._constraints[model_name]
90
+ ):
91
+ if (
92
+ self._get_failure_percentage(
93
+ metric, self._constraints[model_name][metric.tag]
94
+ )
95
+ > 0
96
+ ):
97
+ return False
98
+
99
+ return True
100
+
101
+ def constraint_failure_percentage(
102
+ self, run_config_measurement: "RunConfigMeasurement"
103
+ ) -> float:
104
+ """
105
+ Additive percentage, for every measurement, in every model, of how much
106
+ the RCM is failing the constraints by
107
+
108
+ Returns
109
+ -------
110
+ float
111
+ """
112
+ failure_percentage: float = 0
113
+
114
+ if self._constraints:
115
+ for model_name, model_metrics in run_config_measurement.data().items():
116
+ for metric in model_metrics:
117
+ if self._metric_matches_constraint(
118
+ metric, self._constraints[model_name]
119
+ ):
120
+ failure_percentage += self._get_failure_percentage(
121
+ metric, self._constraints[model_name][metric.tag]
122
+ )
123
+
124
+ return failure_percentage * 100
125
+
126
+ def _metric_matches_constraint(
127
+ self, metric: Record, constraint: ModelConstraints
128
+ ) -> bool:
129
+ if constraint.has_metric(metric.tag):
130
+ return True
131
+ else:
132
+ return False
133
+
134
+ def _get_failure_percentage(
135
+ self, metric: Record, constraint: Dict[str, int]
136
+ ) -> float:
137
+ failure_percentage = 0
138
+
139
+ if "min" in constraint:
140
+ if metric.value() < constraint["min"]:
141
+ failure_percentage = (constraint["min"] - metric.value()) / constraint[
142
+ "min"
143
+ ]
144
+ if "max" in constraint:
145
+ if metric.value() > constraint["max"]:
146
+ failure_percentage = (metric.value() - constraint["max"]) / constraint[
147
+ "max"
148
+ ]
149
+
150
+ return failure_percentage
@@ -0,0 +1,354 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ import logging
18
+ from copy import deepcopy
19
+ from functools import total_ordering
20
+ from statistics import mean
21
+
22
+ from model_analyzer.constants import COMPARISON_SCORE_THRESHOLD, LOGGER_NAME
23
+ from model_analyzer.record.record import RecordType
24
+
25
+ logger = logging.getLogger(LOGGER_NAME)
26
+
27
+
28
+ @total_ordering
29
+ class ModelConfigMeasurement:
30
+ """
31
+ Encapsulates the set of non-gpu metrics obtained from a single model config's
32
+ RunConfig run
33
+ """
34
+
35
+ def __init__(self, model_config_name, model_specific_pa_params, non_gpu_data):
36
+ """
37
+ model_config_name : string
38
+ The model config name that was used in the RunConfig
39
+ model_specific_pa_params: dict
40
+ Dictionary of PA parameters that can change between models
41
+ in a multi-model RunConfig
42
+ non_gpu_data : list of Records
43
+ Metrics that do not have a GPU UUID associated with them,
44
+ from either CPU or PA
45
+ """
46
+
47
+ self._model_config_name = model_config_name
48
+ self._model_specific_pa_params = model_specific_pa_params
49
+ self._non_gpu_data = non_gpu_data
50
+
51
+ self._non_gpu_data_from_tag = self._get_non_gpu_data_from_tag()
52
+
53
+ # Set a default metric weighting
54
+ self._metric_weights = {"perf_throughput": 1}
55
+
56
+ def to_dict(self):
57
+ mcm_dict = deepcopy(self.__dict__)
58
+ del mcm_dict["_metric_weights"]
59
+
60
+ return mcm_dict
61
+
62
+ @classmethod
63
+ def from_dict(cls, model_config_measurement_dict):
64
+ model_config_measurement = ModelConfigMeasurement(None, {}, [])
65
+
66
+ model_config_measurement._model_config_name = model_config_measurement_dict[
67
+ "_model_config_name"
68
+ ]
69
+ model_config_measurement._model_specific_pa_params = (
70
+ model_config_measurement_dict["_model_specific_pa_params"]
71
+ )
72
+
73
+ model_config_measurement._non_gpu_data = cls._deserialize_non_gpu_data(
74
+ model_config_measurement, model_config_measurement_dict["_non_gpu_data"]
75
+ )
76
+
77
+ model_config_measurement._non_gpu_data_from_tag = (
78
+ cls._get_non_gpu_data_from_tag(model_config_measurement)
79
+ )
80
+
81
+ return model_config_measurement
82
+
83
+ def set_metric_weighting(self, metric_objectives):
84
+ """
85
+ Sets the metric weighting for this measurement based
86
+ on the objectives
87
+
88
+ Parameters
89
+ ----------
90
+ metric_objectives : dict of RecordTypes
91
+ keys are the metric types, and values are the relative importance
92
+ of the keys with respect to each other
93
+ """
94
+ self._metric_weights = {
95
+ objective: (value / sum(metric_objectives.values()))
96
+ for objective, value in metric_objectives.items()
97
+ }
98
+
99
+ def model_config_name(self):
100
+ """
101
+ Return the model_config name
102
+ used to get this measurement
103
+ """
104
+
105
+ return self._model_config_name
106
+
107
+ def model_name(self):
108
+ """
109
+ Return the model name
110
+
111
+ TODO: This method should be replaced with the extract_model_name_from_variant_name() static method,
112
+ once the ensemble code gets merged to main
113
+ """
114
+
115
+ return self._model_config_name.partition("_config_")[0]
116
+
117
+ def model_specific_pa_params(self):
118
+ """
119
+ Return a dict of model specific PA parameters
120
+ used in this measurement
121
+ """
122
+
123
+ return self._model_specific_pa_params
124
+
125
+ def non_gpu_data(self):
126
+ """
127
+ Return a list of the non-GPU specific
128
+ measurement Records
129
+ """
130
+
131
+ return self._non_gpu_data
132
+
133
+ def get_metric(self, tag):
134
+ """
135
+ Parameters
136
+ ----------
137
+ tag : str
138
+ A human readable tag that corresponds
139
+ to a particular metric
140
+
141
+ Returns
142
+ -------
143
+ Record
144
+ metric Record corresponding to
145
+ the tag, in this measurement, None
146
+ if tag not found.
147
+ """
148
+
149
+ if tag in self._non_gpu_data_from_tag:
150
+ return self._non_gpu_data_from_tag[tag]
151
+ else:
152
+ return None
153
+
154
+ def get_metric_value(self, tag, default_value=0):
155
+ """
156
+ Parameters
157
+ ----------
158
+ tag : str
159
+ A human readable tag that corresponds
160
+ to a particular metric
161
+ default_value : any
162
+ Value to return if tag is not found
163
+
164
+ Returns
165
+ -------
166
+ Record
167
+ Value of the metric Record corresponding
168
+ to the tag, in this measurement,
169
+ default_value if tag not found.
170
+ """
171
+
172
+ metric = self.get_metric(tag)
173
+ if metric is None:
174
+ return default_value
175
+ return metric.value()
176
+
177
+ def get_weighted_score(self, other):
178
+ """
179
+ Parameters
180
+ ----------
181
+ other: ModelConfigMeasurement
182
+ set of (non_gpu) metrics to be compared against
183
+
184
+ Returns
185
+ -------
186
+ float
187
+ The weighted score between this ModelConfig
188
+ and the other ModelConfig
189
+ """
190
+ return self._calculate_weighted_score(other)
191
+
192
+ def is_better_than(self, other):
193
+ """
194
+ Checks whether a measurement is better than
195
+ another
196
+
197
+ If True, this means this measurement is better
198
+ than the other.
199
+
200
+ Parameters
201
+ ----------
202
+ other: ModelConfigMeasurement
203
+ set of (non_gpu) metrics to be compared against
204
+ """
205
+
206
+ return self._compare_measurements(other) == 1
207
+
208
+ def __eq__(self, other):
209
+ """
210
+ Check whether two sets of measurements are equivalent
211
+
212
+ Parameters
213
+ ----------
214
+ other: ModelConfigMeasurement
215
+ set of (non_gpu) metrics to be compared against
216
+ """
217
+
218
+ return self._compare_measurements(other) == 0
219
+
220
+ def __lt__(self, other):
221
+ """
222
+ Checks whether a measurement is better than
223
+ another
224
+
225
+ This is used when sorting
226
+
227
+ Parameters
228
+ ----------
229
+ other: ModelConfigMeasurement
230
+ set of (non_gpu) metrics to be compared against
231
+
232
+ Returns
233
+ -------
234
+ bool:
235
+ True if other is better than or equal to self
236
+ """
237
+
238
+ return not self.is_better_than(other)
239
+
240
+ def _compare_measurements(self, other):
241
+ """
242
+ Compares two ModelConfig measurements
243
+ based on the weighted metric objectives
244
+
245
+ Parameters
246
+ ----------
247
+ other : ModelConfigMeasurement
248
+ set of (non_gpu) metrics to be compared against
249
+
250
+ Returns
251
+ -------
252
+ int
253
+ 0
254
+ if the results are determined
255
+ to be the same within a threshold
256
+ 1
257
+ if self > other (is better than)
258
+ -1
259
+ if self < other (is worse than)
260
+ """
261
+ weighted_score = self._calculate_weighted_score(other)
262
+
263
+ if weighted_score > COMPARISON_SCORE_THRESHOLD:
264
+ return 1
265
+ elif weighted_score < -COMPARISON_SCORE_THRESHOLD:
266
+ return -1
267
+ return 0
268
+
269
+ def _calculate_weighted_score(self, other):
270
+ """
271
+ Calculates the weighted score between two
272
+ ModelConfig measurements based on the weighted
273
+ metric objectives
274
+
275
+ Parameters
276
+ ----------
277
+ other : ModelConfigMeasurement
278
+ set of (non_gpu) metrics to be compared against
279
+
280
+ Returns
281
+ -------
282
+ float
283
+ The weighted score. A positive value indicates
284
+ this ModelConfig measurement is better than the other
285
+ """
286
+
287
+ weighted_score = 0.0
288
+ for objective, weight in self._metric_weights.items():
289
+ self_metric = self.get_metric(tag=objective)
290
+ other_metric = other.get_metric(tag=objective)
291
+
292
+ # Handle the case where objective GPU metric is queried on CPU only
293
+ if self_metric and other_metric is None:
294
+ return 1
295
+ elif other_metric and self_metric is None:
296
+ return -1
297
+ elif self_metric is None and other_metric is None:
298
+ return 0
299
+
300
+ metric_diff = self_metric - other_metric
301
+ average = mean([self_metric.value(), other_metric.value()])
302
+ weighted_score += weight * (metric_diff.value() / average)
303
+
304
+ return weighted_score
305
+
306
+ def calculate_weighted_percentage_gain(self, other):
307
+ """
308
+ Calculates the weighted percentage between two
309
+ ModelConfig measurements based on the weighted
310
+ metric objectives
311
+
312
+ Parameters
313
+ ----------
314
+ other : ModelConfigMeasurement
315
+ set of (non_gpu) metrics to be compared against
316
+
317
+ Returns
318
+ -------
319
+ float
320
+ The weighted percentage gain. A positive value indicates
321
+ this ModelConfig measurement is better than the other
322
+ """
323
+
324
+ weighted_pct = 0.0
325
+ for objective, weight in self._metric_weights.items():
326
+ self_metric = self.get_metric(tag=objective)
327
+ other_metric = other.get_metric(tag=objective)
328
+
329
+ # Handle the case where objective GPU metric is queried on CPU only
330
+ if self_metric and other_metric is None:
331
+ return 100
332
+ elif other_metric and self_metric is None:
333
+ return -100
334
+ elif self_metric is None and other_metric is None:
335
+ return 0
336
+
337
+ metric_pct = self_metric.calculate_percentage_gain(other_metric)
338
+
339
+ weighted_pct += metric_pct * weight
340
+
341
+ return weighted_pct
342
+
343
+ def _get_non_gpu_data_from_tag(self):
344
+ return {metric.tag: metric for metric in self._non_gpu_data}
345
+
346
+ def _deserialize_non_gpu_data(self, serialized_non_gpu_data):
347
+ non_gpu_data = []
348
+
349
+ for [tag, record_dict] in serialized_non_gpu_data:
350
+ record_type = RecordType.get(tag)
351
+ record = record_type.from_dict(record_dict)
352
+ non_gpu_data.append(record)
353
+
354
+ return non_gpu_data
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ class ModelConstraints:
19
+ """
20
+ A class representing the Constraints used for a single model.
21
+ """
22
+
23
+ def __init__(self, constraints):
24
+ """
25
+ Parameters
26
+ ----------
27
+ constraints: dict
28
+ keys are strings and
29
+ values are dict of single str: int pair
30
+ """
31
+
32
+ self._constraints = {}
33
+ if constraints:
34
+ self._constraints = constraints
35
+
36
+ def to_dict(self):
37
+ """
38
+ Returns constraints dictionary
39
+
40
+ Returns
41
+ ----------
42
+ constraints: dict
43
+ """
44
+ return self._constraints
45
+
46
+ def has_metric(self, name):
47
+ """
48
+ To check if given metric tag is present in constraints
49
+
50
+ Returns
51
+ ----------
52
+ bool:
53
+ True if metric is present in constraints else False
54
+ """
55
+ if name and name in self._constraints:
56
+ return True
57
+ else:
58
+ return False
59
+
60
+ def __getitem__(self, name):
61
+ """
62
+ To subscript constraints using metric name
63
+ ex: model_constraints['perf_latency_p99']
64
+
65
+ Parameters
66
+ ----------
67
+ name: str
68
+ metric name
69
+ """
70
+ if name in self._constraints:
71
+ return self._constraints[name]
72
+ else:
73
+ msg = f"'{name}' key not found in constraints"
74
+ raise KeyError(msg)
75
+
76
+ def __bool__(self):
77
+ """
78
+ To check if constraints are empty
79
+ """
80
+ if self._constraints:
81
+ return True
82
+ else:
83
+ return False
84
+
85
+ def __eq__(self, other):
86
+ """
87
+ To compare two ModelConstraints objects
88
+
89
+ Parameters
90
+ ----------
91
+ other: ModelConstraints object
92
+ """
93
+ if self._constraints == other._constraints:
94
+ return True
95
+ else:
96
+ return False
97
+
98
+ def items(self):
99
+ return self._constraints.items()
100
+
101
+ def __repr__(self):
102
+ return str(self._constraints)
103
+
104
+ def __iter__(self):
105
+ return iter(self._constraints)