-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TVM] inference script #412
[TVM] inference script #412
Conversation
@valentina-kustikova, я унаследовал |
@Rodimkov, в текущем PR будет располагаться реализация вывода. Просьба - отслеживать состояние реализации. |
@valentina-kustikova, решил попробовать разделить эти скрипты по фреймворкам. Тогда вопрос: имеет ли смысл их засунуть в отдельную папку TVM? |
@valentina-kustikova, пока промежуточный результат примерно такой:
По итогу получается, что в обоих случаях придется в конфигах таскать много параметров |
return f'{common_params}' | ||
|
||
|
||
class MXNet_TVMProcess(TVMProcess): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Может, назвать класс TVMProcessMXNetFormat
?
src/inference/tvm_auxiliary.py
Outdated
model, params = tvm.relay.frontend.from_mxnet(net, shape_dict) | ||
with tvm.transform.PassContext(opt_level=3): | ||
lib = tvm.relay.build(model, target=target, params=params) | ||
module = tvm.contrib.graph_executor.GraphModule(lib["default"](dev)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Может быть, конвертацию под каждый фреймворк стоит вынести в отдельный метод?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Предлагаю сделать их приватными и вызывать в обертке в зависимости от фреймворка
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def convert_model(self, framework):
if framework == 'mxnet':
_convert_from_mxnet(self)
Как-то так примерно
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def _convert_from_mxnet(self):
import mxnet, gluoncv
if self.args['device'] == 'CPU':
context = mxnet.cpu()
model_name = self.args['model_name']
log.info(f'Loading network \"{model_name}\" from GluonCV model zoo')
net = gluoncv.model_zoo.get_model(model_name, pretrained=True, ctx=context)
shape_dict = {self.args['input_name']: self.args['input_shape']}
log.info('Creating graph module from MXNet model')
model, params = tvm.relay.frontend.from_mxnet(net, shape_dict)
with tvm.transform.PassContext(opt_level=3):
lib = tvm.relay.build(model, target=target, params=params)
module = tvm.contrib.graph_executor.GraphModule(lib["default"](dev))
return module
def convert_model(self, framework):
if framework == 'mxnet':
module = self._convert_from_mxnet()
return module
elif framework == 'pytorch':
...
Вопросы 1 и 3 связанные, договорились, что делаем несколько скриптов. Вопрос 2: input blob size в csv получается в результате парсинга того, что логирует скрипт инференса вот в этой строке: log.info(f'Shape for input layer {args.input_name}: {args.input_shape}') |
@valentina-kustikova, немного переделал вспомогательный модуль, потому что проблему #412 (comment) я недооценил, она возникает, на самом деле, у всех фреймворков, просто я не создавал объекты |
@ismukhin, не понятно, удалось ли побороть первую проблему? По второму в трассе тестов (если по ним нажать) написано: Traceback (most recent call last):\n', ' File "/home/runner/work/dl-benchmark/dl-benchmark/src/inference/inference_tvm_pytorch.py", line 208, in main\n', ' graph_module = converter.get_graph_module()\n', ' File "/home/runner/work/dl-benchmark/dl-benchmark/src/inference/tvm_auxiliary.py", line 30, in get_graph_module\n', ' module = self._convert_model_from_framework(target, dev)\n', ' File "/home/runner/work/dl-benchmark/dl-benchmark/src/inference/inference_tvm_pytorch.py", line 143, in _convert_model_from_framework\n', ' pt_model = pt_model(weights=True)\n', "TypeError: init() got an unexpected keyword argument 'weights'\n", т.е. pt_model получает неожиданный аргумент, у него просто нет такого аргумента. Проверять работу тестов можно локально, запуская скрипт, там пишется лог с ошибками. |
Первую проблему удалось решить в таком варианте, который я залил. |
Надо попробовать локально запустить smoke-тест, только ваш и посмотреть результат. |
@valentina-kustikova, оказалось, что имя модели нужно задавать только буквами нижнего регистра. |
@ismukhin, можно ревьюить все, что сделано? Статус пока драфт, поэтому и спрашиваю. |
Можно |
В PyTorch пока что поддержка только моделей из torchvision модуля, поддержку моделей из файлов, думаю, занесу вместе с TF и TFLite |
Хорошо, тогда переводите из состояния драфт, оставлю ревью. @Rodimkov, предлагаю вам тоже посмотреть разработанный код. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Нужно еще обновить README с описанием инференс-скриптов + шаблонный файл конфигурации + README к шаблонному файлу конфигурации.
|
||
common_params = (f'-i {dataset} ' | ||
f'-is {input_shape} -b {batch_size} -ni {iteration} ' | ||
f'--report_path {self.report_path}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лучше в 2 строки написать, а не 3.
common_params = (f'-m {model_json} -w {model_params} ') | ||
else: | ||
raise Exception('Incorrect model parameters. Set model name or file names.') | ||
path_to_sync_script = Path.joinpath(self.inference_script_root, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лучше переименовать в path_to_script
, поскольку здесь явно режимов нет.
common_params = (f'-m {model_json} -w {model_params} ') | ||
else: | ||
raise Exception('Incorrect model parameters. Set model name or file names.') | ||
path_to_sync_script = Path.joinpath(self.inference_script_root, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лучше переименовать в path_to_script, поскольку здесь явно режимов нет.
def _fill_command_line(self): | ||
model = self._test.model.model | ||
common_params = f'-m {model} ' | ||
path_to_sync_script = Path.joinpath(self.inference_script_root, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лучше переименовать в path_to_script, поскольку здесь явно режимов нет.
src/inference/inference_tvm_mxnet.py
Outdated
shape_dict = {self.args['input_name']: self.args['input_shape']} | ||
log.info('Creating graph module from MXNet model') | ||
model, params = tvm.relay.frontend.from_mxnet(net, shape_dict) | ||
with tvm.transform.PassContext(opt_level=3): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вот здесь выставляется уровень оптимизации, но не понятно, почему именно такой?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
В TVM по умолчанию 2, если не указывать явно. Но в примерах и прочем используют 3. Возможно стоит задать параметром, это влияет на производительность.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А на этот параметр есть какие-то ограничения? Потому что я выставляю и 10, и 100, и 1000 и оно работает.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Как я понимаю там стоит условие, что оптимизация используется если ее уровень не меньше указанного в opt_level. Максимальный уровень у оптимизаций 4, то есть при opt_level=4
и выше будут включены все оптимизации.
src/inference/inference_tvm_mxnet.py
Outdated
log.info('Converting output tensor to print results') | ||
res = prepare_output(result, args.task, args.output_names) | ||
log.info('Inference results') | ||
io.process_output(res, log) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Во всех скриптах вывода есть параметр raw_output
, поэтому печать выполняется так, как показано ниже. В целом по структуре (логические отступы и прочее) основной функции надо посмотреть в других скриптах вывода, например, в onnx
if not args.raw_output:
if args.number_iter == 1:
try:
log.info('Converting output tensor to print results')
result = prepare_output(result, args.output_names, args.model_name, args.task, args)
log.info('Inference results')
io.process_output(result, log)
except Exception as ex:
log.warning('Error when printing inference results. {0}'.format(str(ex)))
log.info(f'Performance results:\n{json.dumps(inference_result, indent=4)}')
src/inference/inference_tvm_onnx.py
Outdated
log.info('Converting output tensor to print results') | ||
res = prepare_output(result, args.task, args.output_names) | ||
log.info('Inference results') | ||
io.process_output(res, log) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Аналогичный комментарий.
module.set_input(input_name, slice_input[input_name]) | ||
module.run() | ||
res = module.get_output(0) | ||
return res |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А мы можем вот эти три функции вытащить в отдельный скрипт? Если я правильно вижу, то они дублируются для всех фреймворков.
log.info('Converting output tensor to print results') | ||
res = prepare_output(result, args.task, args.output_names) | ||
log.info('Inference results') | ||
io.process_output(res, log) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Аналогичный комментарий касательно структуры скрипта.
if device == 'CPU': | ||
log.info(f'Inference will be executed on {device}') | ||
target = tvm.target.Target('llvm') | ||
dev = tvm.cpu(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А если передан не CPU
? Тем более, что вроде бы для MXNet фигурирует NVIDIA_GPU.
src/inference/transformer.py
Outdated
self._converting['mean'][1], | ||
self._converting['mean'][2]]) | ||
for i in range(image.shape[2]): | ||
image[:, :, i] /= 255 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А зачем тут всегда делать на 255?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Я предполагаю, что std и mean подаются в диапазоне от [0,1], поэтому все пиксели изображения нормируются. В любом случае, нормировка — опциональный параметр. И я пока что имел дело только с ImageNET'овскими std и mean, которые бывают как нормированные, так и не нормированные.
@valentina-kustikova, исправления выложил |
@@ -17,6 +17,7 @@ | |||
- [OpenCV][opencv]. | |||
- [MXNet][mxnet]. | |||
- [PyTorch][pytorch]. | |||
- [TVM][tvm]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
В основном readme в корне репозитория тоже надо добавить такую строчку.
@maslovaz, @n-berezina-nn, написали поддержку бенчмаркинга средствами TVM моделей в формате MXNet, PyTorch, ONNRuntime. Посмотрите, пожалуйста. Отдельным пулл-реквестом добавим поддержку бенчмаркинга моделей в формате TensorFlow, TensorFlow lite и оптимизированных моделей в формате TVM. |
@ismukhin, обновите, пожалуйста, этот статус в соответствии с тем, что сейчас сделано. Спасибо! |
@maslovaz, @n-berezina-nn, посмотрите, или мы заливаем? |
TODO:
README
для скриптов инференса и для бенчмарка