Skip to content

[TVM] Relax API #576

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

Merged
merged 19 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion demo/benchmark_configs/TVM.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<ChannelSwap></ChannelSwap>
<Target>llvm</Target>
<Layout>NCHW</Layout>
<VirtualMachine>False</VirtualMachine>
<HighLevelAPI>Relay</HighLevelAPI>
<OptimizationLevel>3</OptimizationLevel>
</FrameworkDependent>
</Test>
Expand Down
37 changes: 31 additions & 6 deletions docker/TVM/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,45 @@ RUN wget -q --no-check-certificate -c https://repo.anaconda.com/miniconda/Minico
./miniconda3/bin/conda create -n tvm-env -y python=3.7.16 && \
rm -rf /root/miniconda3/pkgs/* && \
rm ~/Miniconda3-latest-Linux-x86_64.sh -f

ENV PATH /root/miniconda3/envs/tvm-env/bin:/root/miniconda3/bin:$PATH
RUN echo "source activate tvm-env" > ~/.bashrc
RUN export LD_LIBRARY_PATH=/root/miniconda3/envs/tvm-env/lib:${LD_LIBRARY_PATH}
RUN conda config --add channels intel

# Installing dependencies
RUN python3 -m pip install pycocotools docker PyYAML
RUN python3 -m pip install pycocotools docker PyYAML gluoncv[full] opencv-python Cython psutil
RUN apt-get update && apt-get install -y ffmpeg libsm6 libxext6
RUN python3 -m pip install gluoncv[full]
RUN python3 -m pip install opencv-python

RUN apt-get update && apt-get install -y -qq --no-install-recommends cmake software-properties-common
RUN apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main" && \
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
RUN apt-get update && \
apt-get install -y -qq --no-install-recommends llvm-19 llvm-19-dev && \
rm -rf /var/lib/apt/lists/*

# Installing Apache-TVM
RUN python3 -m pip install apache-tvm==0.14.dev264
ARG TVM_VERSION=v0.20.0

RUN git clone --recursive https://github.com/apache/tvm tvm --branch ${TVM_VERSION} --single-branch
ENV TVM_BUILD_DIR=/tmp/build-tvm
RUN mkdir $TVM_BUILD_DIR && cd $TVM_BUILD_DIR
RUN cp /root/tvm/cmake/config.cmake .
RUN echo "set(CMAKE_BUILD_TYPE RelWithDebInfo)" >> config.cmake
RUN echo "set(USE_LLVM /usr/bin/llvm-config-19)" >> config.cmake
RUN echo "set(HIDE_PRIVATE_SYMBOLS ON)" >> config.cmake
RUN echo "set(USE_CUDA OFF)" >> config.cmake
RUN echo "set(USE_METAL OFF)" >> config.cmake
RUN echo "set(USE_VULKAN OFF)" >> config.cmake
RUN echo "set(USE_OPENCL OFF)" >> config.cmake
RUN echo "set(USE_CUBLAS OFF)" >> config.cmake
RUN echo "set(USE_CUDNN OFF)" >> config.cmake
RUN echo "set(USE_CUTLASS OFF)" >> config.cmake

RUN /bin/bash -c 'cmake /root/tvm/ && cmake --build . -- -j$(nproc --all)'

WORKDIR /root/
RUN export TVM_LIBRARY_PATH=$TVM_BUILD_DIR
RUN python3 -m pip install -e /root/tvm/python

# ARG
ARG TORCH_VERSION=2.0.1
Expand Down
17 changes: 9 additions & 8 deletions src/benchmark/frameworks/tvm/tvm_parameters_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def parse_parameters(self, curr_test):
CONFIG_FRAMEWORK_DEPENDENT_STD_TAG = 'Std'
CONFIG_FRAMEWORK_DEPENDENT_CHANNEL_SWAP_TAG = 'ChannelSwap'
CONFIG_FRAMEWORK_DEPENDENT_LAYOUT_TAG = 'Layout'
CONFIG_FRAMEWORK_DEPENDENT_VIRTUAL_MACHINE = 'VirtualMachine'
CONFIG_FRAMEWORK_DEPENDENT_HIGH_LEVEL_API = 'HighLevelAPI'

dep_parameters_tag = curr_test.getElementsByTagName(CONFIG_FRAMEWORK_DEPENDENT_TAG)[0]

Expand All @@ -39,8 +39,8 @@ def parse_parameters(self, curr_test):
CONFIG_FRAMEWORK_DEPENDENT_LAYOUT_TAG)[0].firstChild
_target = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_TARGET)[0].firstChild
_vm = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_VIRTUAL_MACHINE)[0].firstChild
_high_level_api = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_HIGH_LEVEL_API)[0].firstChild

return TVMParameters(
framework=_framework.data if _framework else None,
Expand All @@ -53,14 +53,15 @@ def parse_parameters(self, curr_test):
optimization_level=_optimization_level.data if _optimization_level else None,
layout=_layout.data if _layout else None,
target=_target.data if _target else None,
vm=_vm.data if _vm else None,
high_level_api=_high_level_api.data if _high_level_api else None,
)


class TVMParameters(FrameworkParameters):
def __init__(self, framework, input_name, input_shape,
normalize, mean, std, channel_swap,
optimization_level, layout, target, vm):
optimization_level, layout, target,
high_level_api):
self.framework = None
self.input_name = None
self.input_shape = None
Expand All @@ -71,7 +72,7 @@ def __init__(self, framework, input_name, input_shape,
self.optimization_level = None
self.layout = None
self.target = 'llvm'
self.vm = None
self.high_level_api = None

if self._framework_is_correct(framework):
self.framework = framework
Expand All @@ -93,8 +94,8 @@ def __init__(self, framework, input_name, input_shape,
self.layout = layout
if self._parameter_is_not_none(target):
self.target = target
if self._parameter_is_not_none(vm):
self.vm = vm
if self._parameter_is_not_none(high_level_api):
self.high_level_api = high_level_api

@staticmethod
def _framework_is_correct(framework):
Expand Down
9 changes: 4 additions & 5 deletions src/benchmark/frameworks/tvm/tvm_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@ def _fill_command_line(self):
common_params = TVMProcess._add_flag_to_cmd_line(
common_params, '--norm')

vm = self._test.dep_parameters.vm
if vm == 'True':
common_params = TVMProcess._add_flag_to_cmd_line(
common_params, '-vm')

mean = self._test.dep_parameters.mean
common_params = TVMProcess._add_optional_argument_to_cmd_line(
common_params, '--mean', mean)
Expand All @@ -86,6 +81,10 @@ def _fill_command_line(self):
common_params = TVMProcess._add_optional_argument_to_cmd_line(
common_params, '--target', target)

high_level_api = self._test.dep_parameters.high_level_api
common_params = TVMProcess._add_optional_argument_to_cmd_line(
common_params, '--high_level_api', high_level_api)

return f'{common_params}'


Expand Down
3 changes: 2 additions & 1 deletion src/configs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@
изображения.
- `ChannelSwap` - тег, необязательный для заполнения. Описывает изменение порядка каналов на
входном изображении. По умолчанию будет установлен порядок (2, 0, 1), что соответствует BGR.
- `HighLevelAPI` - тег, необязательный для заполнения. Определяет используемое высокоуровневое API: `Relay`, `RelayVM` или `RelaxVM`. По умолчанию задается значение `Relay`.
- `OptimizationLevel` - тег, необязательный для заполнения. Определяет уровень оптимизаций для
графа вычислений, которые ускоряют инференс. По умолчанию оптимизации не применяются.
- `Framework` - тег, обязательный для заполнения. Определяет фреймворк, модели которого будут
Expand Down Expand Up @@ -766,7 +767,7 @@
<ChannelSwap></ChannelSwap>
<Layout>NCHW</Layout>
<Target>llvm</Target>
<VirtualMachine>True</VirtualMachine>
<HighLevelAPI>RelaxVM</HighLevelAPI>
<OptimizationLevel>3</OptimizationLevel>
</FrameworkDependent>
</Test>
Expand Down
36 changes: 1 addition & 35 deletions src/configs/benchmark_configuration_file_template.xml
Original file line number Diff line number Diff line change
Expand Up @@ -416,41 +416,7 @@
<Std></Std>
<Layout></Layout>
<ChannelSwap></ChannelSwap>
<VirtualMachine></VirtualMachine>
<Target></Target>
<OptimizationLevel></OptimizationLevel>
</FrameworkDependent>
</Test>
<Test>
<Model>
<Task></Task>
<Name></Name>
<Precision></Precision>
<SourceFramework>TVM</SourceFramework>
<ModelPath></ModelPath>
<WeightsPath></WeightsPath>
</Model>
<Dataset>
<Name></Name>
<Path></Path>
</Dataset>
<FrameworkIndependent>
<InferenceFramework>TVM</InferenceFramework>
<BatchSize></BatchSize>
<Device></Device>
<IterationCount></IterationCount>
<TestTimeLimit></TestTimeLimit>
</FrameworkIndependent>
<FrameworkDependent>
<InputName></InputName>
<InputShape></InputShape>
<Framework></Framework> <!--Принимает значения: caffe, onnx, pytorch, mxnet, tvm, tflite-->
<Normalize></Normalize>
<Mean></Mean>
<Std></Std>
<Layout></Layout>
<ChannelSwap></ChannelSwap>
<VirtualMachine></VirtualMachine>
<HighLevelAPI></HighLevelAPI>
<Target></Target>
<OptimizationLevel></OptimizationLevel>
</FrameworkDependent>
Expand Down
1 change: 1 addition & 0 deletions src/inference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,7 @@ inference_tvm.py
ImageNet.
- `-ni / --number_iter` - количество прямых проходов по сети.
По умолчанию выполняется один проход по сети.
- `--high_level_api` - высокоуровневое API: `Relay`, `RelayVM` или `RelaxVM`. По умолчанию `Relay`.
- `-ol / --opt_level` - параметр, определяющий уровень оптимизации
графа вычислений нейронной сети для ускорения инференса. По умолчанию
оптимизации не применяются.
Expand Down
13 changes: 7 additions & 6 deletions src/inference/inference_tvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,12 @@ def cli_argument_parser():
default=0.5,
type=float,
dest='threshold')
parser.add_argument('-vm', '--virtual_machine',
help='Flag to use VirtualMachine API',
action='store_true',
dest='vm')
parser.add_argument('--high_level_api',
help='Type of high level API',
choices=['Relay', 'RelayVM', 'RelaxVM'],
default='Relay',
type=str,
dest='high_level_api')
parser.add_argument('--raw_output',
help='Raw output without logs.',
default=False,
Expand Down Expand Up @@ -209,8 +211,7 @@ def main():
args.input_name,
io.get_slice_input,
args.time,
args.vm)

args.high_level_api)
if not args.raw_output:
if args.number_iter == 1:
try:
Expand Down
37 changes: 27 additions & 10 deletions src/inference/tvm_auxiliary.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ def _infer_slice(self, input_name, module, slice_input):
pass

@staticmethod
def get_helper(vm):
if vm:
return InferenceVMApi()
else:
def get_helper(high_level_api):
if high_level_api == 'Relay':
return InferenceRelayAPI()
elif high_level_api == 'RelayVM':
return InferenceRelayVMApi()
elif high_level_api == 'RelaxVM':
return InferenceRelaxVMApi()

@abc.abstractmethod
def _inference_tvm(self, module, input_name, slice_input):
Expand Down Expand Up @@ -77,22 +79,37 @@ def _inference_tvm(self, module, input_name, slice_input):
return [module.get_output(i) for i in range(num_of_outputs)]


class InferenceVMApi(InferenceHelper):
class InferenceRelayVMApi(InferenceHelper):
def __init__(self):
super().__init__()

def _infer_slice(self, input_name, module, slice_input):
module.set_input('main', slice_input[input_name])
module.run()
res = module.get_outputs()
return res
return module.get_outputs()

def _inference_tvm(self, module, input_name, slice_input):
module.set_input('main', slice_input[input_name])
module.run()
return module.get_outputs()


class InferenceRelaxVMApi(InferenceHelper):
def __init__(self):
super().__init__()

def _infer_slice(self, input_name, module, slice_input):
module.set_input('main', slice_input[input_name])
module.invoke_stateful('main')
return module.get_outputs('main')

def _inference_tvm(self, module, input_name, slice_input):
import tvm
module.set_input('main', slice_input[input_name])
module.invoke_stateful('main')
return [tvm.nd.array(module.get_outputs('main'))]


class OutputPreparer:
def __init__(self, source_framework):
self.source_framework = source_framework
Expand Down Expand Up @@ -163,7 +180,7 @@ def create_dict_for_converter(args):
'opt_level': args.opt_level,
'target': args.target,
'module': args.module,
'vm': args.vm,
'high_level_api': args.high_level_api,
'source_framework': args.source_framework,
}
return dictionary
Expand Down Expand Up @@ -199,8 +216,8 @@ def create_dict_for_output_preparer(args):
return dictionary


def inference_tvm(module, num_of_iterations, input_name, get_slice, test_duration, vm):
inference_helper = InferenceHelper.get_helper(vm)
def inference_tvm(module, num_of_iterations, input_name, get_slice, test_duration, high_level_api):
inference_helper = InferenceHelper.get_helper(high_level_api)
return inference_helper.inference_tvm(module, num_of_iterations, input_name, get_slice, test_duration)


Expand Down
4 changes: 2 additions & 2 deletions src/model_converters/tvm_converter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ tvm_compiler.py --mod <model> \
--params <parameters> \
--target <target> \
--opt_level <opt_level> \
--virtual_machine <virtual_machine> \
--high_level_api <high_level_api> \
--lib_name <lib_name> \
--output_dir <output_dir>
```
Expand All @@ -82,7 +82,7 @@ for the Relay API or to the `.so`+`.ro` format for the VirtualMachine API.
- `-p / --params` is a path to an `.params` file with a model parameters.
- `-t / --target` is target device information, for example `llvm` for CPU.
- `--opt_level` is the optimization level of the task extractions.
- `-vm / --virtual_machine` is a flag to use the VirtualMachine API.
- `--high_level_api` is a high level API: `Relay`, `RelayVM`, `RelaxVM`.
- `--lib_name` is a file name to save compiled model.
- `-op / --output_dir` is a path to save the model.

Expand Down
14 changes: 8 additions & 6 deletions src/model_converters/tvm_converter/tvm_auxiliary/caffe_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ def _convert_model_from_framework(self):

with open(self.model_params, 'rb') as f:
init_net.ParseFromString(f.read())

model, params = self.tvm.relay.frontend.from_caffe(init_net,
predict_net,
shape_dict,
dtype_dict)
return model, params
if self.high_level_api in ['Relay', 'RelayVM']:
model, params = self.tvm.relay.frontend.from_caffe(init_net,
predict_net,
shape_dict,
dtype_dict)
return model, params
else:
raise ValueError(f'API {self.high_level_api} is not supported')
Loading