Skip to content

Commit aab9495

Browse files
authored
Concurrency sweep early backoff (#537)
* Implemented early backoff * Adding get_last_results method to ConfigGeneratorInterface * Ignore type check error * Removing get_last_measurements * Reverting formatting changes * Fixing type checking
1 parent 62c89bf commit aab9495

File tree

3 files changed

+53
-35
lines changed

3 files changed

+53
-35
lines changed

model_analyzer/config/generate/perf_analyzer_config_generator.py

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,9 @@ class PerfAnalyzerConfigGenerator(ConfigGeneratorInterface):
3636
earlier depending on results that it receives
3737
"""
3838

39-
def __init__(self,
40-
cli_config: ConfigCommandProfile,
41-
model_name: str,
42-
model_perf_analyzer_flags: dict,
43-
model_parameters: dict,
44-
early_exit_enable: bool) -> None:
39+
def __init__(self, cli_config: ConfigCommandProfile, model_name: str,
40+
model_perf_analyzer_flags: dict, model_parameters: dict,
41+
early_exit_enable: bool) -> None:
4542
"""
4643
Parameters
4744
----------
@@ -77,8 +74,8 @@ def __init__(self,
7774
self._generator_started = False
7875

7976
self._last_results: List[RunConfigMeasurement] = []
80-
self._concurrency_results: List[RunConfigMeasurement] = []
81-
self._batch_size_results: List[RunConfigMeasurement] = []
77+
self._concurrency_results: List[Optional[RunConfigMeasurement]] = []
78+
self._batch_size_results: List[Optional[RunConfigMeasurement]] = []
8279

8380
self._model_name = model_name
8481
self._perf_analyzer_flags = model_perf_analyzer_flags
@@ -91,6 +88,33 @@ def __init__(self,
9188

9289
self._generate_perf_configs()
9390

91+
@staticmethod
92+
def throughput_gain_valid_helper(
93+
throughputs: List[Optional[RunConfigMeasurement]],
94+
min_tries: int = THROUGHPUT_MINIMUM_CONSECUTIVE_CONCURRENCY_TRIES,
95+
min_gain: float = THROUGHPUT_MINIMUM_GAIN) -> bool:
96+
if len(throughputs) < min_tries:
97+
return True
98+
99+
tputs_in_range = [
100+
PerfAnalyzerConfigGenerator.get_throughput(throughputs[x])
101+
for x in range(-min_tries, 0)
102+
]
103+
104+
first = tputs_in_range[0]
105+
best = max(tputs_in_range)
106+
107+
gain = (best - first) / first
108+
109+
return gain > min_gain
110+
111+
@staticmethod
112+
def get_throughput(measurement: Optional[RunConfigMeasurement]) -> float:
113+
if measurement:
114+
return measurement.get_non_gpu_metric_value('perf_throughput')
115+
else:
116+
return 0.0
117+
94118
def _is_done(self) -> bool:
95119
""" Returns true if this generator is done generating configs """
96120
return self._generator_started and self._done_walking()
@@ -111,7 +135,8 @@ def get_configs(self) -> Generator[PerfAnalyzerConfig, None, None]:
111135

112136
self._step()
113137

114-
def set_last_results(self, measurements: List[Optional[RunConfigMeasurement]]) -> None:
138+
def set_last_results(
139+
self, measurements: List[Optional[RunConfigMeasurement]]) -> None:
115140
"""
116141
Given the results from the last PerfAnalyzerConfig, make decisions
117142
about future configurations to generate
@@ -182,7 +207,8 @@ def _step(self) -> None:
182207

183208
def _add_best_throughput_to_batch_sizes(self) -> None:
184209
if self._concurrency_results:
185-
best = max(self._concurrency_results)
210+
# type is List[Optional[RCM]]
211+
best = max(self._concurrency_results) #type: ignore
186212
self._batch_size_results.append(best)
187213

188214
def _reset_concurrencies(self) -> None:
@@ -231,34 +257,14 @@ def _last_results_erroneous(self) -> bool:
231257

232258
def _concurrency_throughput_gain_valid(self) -> bool:
233259
""" Check if any of the last X concurrency results resulted in valid gain """
234-
return self._throughput_gain_valid_helper(
260+
return PerfAnalyzerConfigGenerator.throughput_gain_valid_helper(
235261
throughputs=self._concurrency_results,
236262
min_tries=THROUGHPUT_MINIMUM_CONSECUTIVE_CONCURRENCY_TRIES,
237263
min_gain=THROUGHPUT_MINIMUM_GAIN)
238264

239265
def _batch_size_throughput_gain_valid(self) -> bool:
240266
""" Check if any of the last X batch_size results resulted in valid gain """
241-
return self._throughput_gain_valid_helper(
267+
return PerfAnalyzerConfigGenerator.throughput_gain_valid_helper(
242268
throughputs=self._batch_size_results,
243269
min_tries=THROUGHPUT_MINIMUM_CONSECUTIVE_BATCH_SIZE_TRIES,
244270
min_gain=THROUGHPUT_MINIMUM_GAIN)
245-
246-
def _throughput_gain_valid_helper(self,
247-
throughputs: List[RunConfigMeasurement],
248-
min_tries: int, min_gain: float) -> bool:
249-
if len(throughputs) < min_tries:
250-
return True
251-
252-
tputs_in_range = [
253-
self._get_throughput(throughputs[x]) for x in range(-min_tries, 0)
254-
]
255-
256-
first = tputs_in_range[0]
257-
best = max(tputs_in_range)
258-
259-
gain = (best - first) / first
260-
261-
return gain > min_gain
262-
263-
def _get_throughput(self, measurement: RunConfigMeasurement) -> float:
264-
return measurement.get_non_gpu_metric_value('perf_throughput')

model_analyzer/config/generate/quick_plus_concurrency_sweep_run_config_generator.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from model_analyzer.config.generate.brute_run_config_generator import BruteRunConfigGenerator
2121
from model_analyzer.config.generate.quick_run_config_generator import QuickRunConfigGenerator
2222
from model_analyzer.config.generate.model_variant_name_manager import ModelVariantNameManager
23+
from model_analyzer.config.generate.perf_analyzer_config_generator import PerfAnalyzerConfigGenerator
2324
from model_analyzer.config.run.run_config import RunConfig
2425
from model_analyzer.triton.client.client import TritonClient
2526
from model_analyzer.device.gpu_device import GPUDevice
@@ -78,6 +79,7 @@ def __init__(self, search_config: SearchConfig,
7879

7980
def set_last_results(
8081
self, measurements: List[Optional[RunConfigMeasurement]]) -> None:
82+
self._last_measurement = measurements[-1]
8183
self._rcg.set_last_results(measurements)
8284

8385
def get_configs(self) -> Generator[RunConfig, None, None]:
@@ -127,10 +129,21 @@ def _sweep_concurrency_over_top_results(
127129

128130
for count, result in enumerate(top_results):
129131
run_config = deepcopy(result.run_config())
132+
133+
run_config_measurements = []
130134
for concurrency in (2**i for i in range(0, 10)):
131135
run_config = self._set_concurrency(run_config, concurrency)
132136
yield run_config
133137

138+
run_config_measurements.append(self._last_measurement)
139+
140+
if not PerfAnalyzerConfigGenerator.throughput_gain_valid_helper(
141+
throughputs=run_config_measurements):
142+
logger.info(
143+
"Terminating concurrency sweep - throughput is decreasing"
144+
)
145+
break
146+
134147
def _set_concurrency(self, run_config: RunConfig,
135148
concurrency: int) -> RunConfig:
136149
for model_run_config in run_config.model_run_configs():

tests/test_perf_analyzer_config_generator.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,8 @@ def _test_throughput_gain_valid_helper(self, throughput_values,
567567
MagicMock(),
568568
early_exit_enable=False)
569569

570-
result = pacg._throughput_gain_valid_helper(throughputs=throughputs,
571-
min_tries=4,
572-
min_gain=0.05)
570+
result = PerfAnalyzerConfigGenerator.throughput_gain_valid_helper(
571+
throughputs=throughputs, min_tries=4, min_gain=0.05)
573572

574573
self.assertEqual(result, expected_result)
575574

0 commit comments

Comments
 (0)