【TVM教程】利用 TVMC Micro 实验微模子

[复制链接]
发表于 2025-10-2 07:54:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Apache TVM是一个深度的深度学习编译框架,实用于 CPU、GPU 和各种呆板学习加快芯片。更多 TVM 中文文档可访问 →https://tvm.hyper.ai/
作者:Andrew Reusch, Mehrdad Hessar
本教程先容怎样用 C runtime 主动调优模子。
安装 microTVM Python 依靠项​

TVM 不包罗用于 Python 串行通讯包,因此在利用 microTVM 之前我们必须先安装一个。我们还须要TFLite来加载模子。
  1. pip install pyserial==3.5 tflite==2.1
  2. # 如果下面的标志为 False,可以跳过下一节(安装 Zephyr)
  3. # 安装 Zephyr 约花费20分钟
  4. import os
  5. use_physical_hw = bool(os.getenv("TVM_MICRO_USE_HW"))
复制代码
安装 Zephyr​

  1. # 安装 west 和 ninja
  2. python3 -m pip install west
  3. apt-get install -y ninja-build
  4. # 安装 ZephyrProject
  5. ZEPHYR_PROJECT_PATH="/content/zephyrproject"
  6. export ZEPHYR_BASE=${ZEPHYR_PROJECT_PATH}/zephyr
  7. west init ${ZEPHYR_PROJECT_PATH}
  8. cd ${ZEPHYR_BASE}
  9. git checkout v3.2-branch
  10. cd ..
  11. west update
  12. west zephyr-export
  13. chmod -R o+w ${ZEPHYR_PROJECT_PATH}
  14. # 安装 Zephyr SDK
  15. cd /content
  16. ZEPHYR_SDK_VERSION="0.15.2"
  17. wget "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZEPHYR_SDK_VERSION}/zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.gz"
  18. tar xvf "zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.gz"
  19. mv "zephyr-sdk-${ZEPHYR_SDK_VERSION}" zephyr-sdk
  20. rm "zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.gz"
  21. # 安装 python 依赖
  22. python3 -m pip install -r "${ZEPHYR_BASE}/scripts/requirements.txt"
复制代码
导入 Python 依靠项​

  1. import json
  2. import numpy as np
  3. import pathlib
  4. import tvm
  5. from tvm.relay.backend import Runtime
  6. import tvm.micro.testing
复制代码
界说模子​

起首在 Relay 中界说一个要在装备上实验的模子,然后从 Relay 模子中创建一个 IRModule,并用随机数添补参数。
  1. data_shape = (1, 3, 10, 10)
  2. weight_shape = (6, 3, 5, 5)
  3. data = tvm.relay.var("data", tvm.relay.TensorType(data_shape, "float32"))
  4. weight = tvm.relay.var("weight", tvm.relay.TensorType(weight_shape, "float32"))
  5. y = tvm.relay.nn.conv2d(
  6.     data,
  7.     weight,
  8.     padding=(2, 2),
  9.     kernel_size=(5, 5),
  10.     kernel_layout="OIHW",
  11.     out_dtype="float32",
  12. )
  13. f = tvm.relay.Function([data, weight], y)
  14. relay_mod = tvm.IRModule.from_expr(f)
  15. relay_mod = tvm.relay.transform.InferType()(relay_mod)
  16. weight_sample = np.random.rand(
  17.     weight_shape[0], weight_shape[1], weight_shape[2], weight_shape[3]
  18. ).astype("float32")
  19. params = {"weight": weight_sample}
复制代码
界说 target​

下面界说形貌实验环境的 TVM target,它与其他 microTVM 教程中的 target 界说非常相似。差别之处是用 C Runtime 来天生模子。
在物理硬件上运行时,选择一个 target 和一个形貌硬件的单板。在本教程的 PLATFORM 列表中可以选择多个硬件目的。运行本教程时用 –platform 参数来选择平台。
  1. RUNTIME = Runtime("crt", {"system-lib": True})
  2. TARGET = tvm.micro.testing.get_target("crt")
  3. # 为物理硬件编译
  4. # --------------------------------------------------------------------------
  5. # 在物理硬件上运行时,选择描述硬件的 TARGET 和 BOARD。
  6. # 下面的示例中选择 STM32L4R5ZI Nucleo。
  7. if use_physical_hw:
  8.     BOARD = os.getenv("TVM_MICRO_BOARD", default="nucleo_l4r5zi")
  9.     SERIAL = os.getenv("TVM_MICRO_SERIAL", default=None)
  10.     TARGET = tvm.micro.testing.get_target("zephyr", BOARD)
复制代码
提取调优任务​

并非上面打印的 Relay 步伐中的全部算子都可以调优,有些算子不是很紧张,以是只界说了一个实现;其他的作为调优任务没故意义。用 extract_from_program,可以天生可调优任务列表。
由于任务提取涉及到运行编译器,以是起首设置编译器的转换 pass;之后在主动调优过程中应用类似的设置。
  1. pass_context = tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True})
  2. with pass_context:
  3.     tasks = tvm.autotvm.task.extract_from_program(relay_mod["main"], {}, TARGET)
  4. assert len(tasks) > 0
复制代码
设置 microTVM​

主动调优前,要界说一个模块加载器,然后将它通报给 tvm.autotvm.LocalBuilder。创建一个 tvm.autotvm.LocalBuilder,并用 builder 和 runner 为主动调优器天生多个测试值。
本教程中可以选择用 x86 主机作为示例,或用来自 Zephyr RTOS 的差别 targets。若用 x86,则通报 –platform=host,也可以从 PLATFORM 列表中选择其他选项。
  1. module_loader = tvm.micro.AutoTvmModuleLoader(
  2.     template_project_dir=pathlib.Path(tvm.micro.get_microtvm_template_projects("crt")),
  3.     project_options={"verbose": False},
  4. )
  5. builder = tvm.autotvm.LocalBuilder(
  6.     n_parallel=1,
  7.     build_kwargs={"build_option": {"tir.disable_vectorize": True}},
  8.     do_fork=True,
  9.     build_func=tvm.micro.autotvm_build_func,
  10.     runtime=RUNTIME,
  11. )
  12. runner = tvm.autotvm.LocalRunner(number=1, repeat=1, timeout=100, module_loader=module_loader)
  13. measure_option = tvm.autotvm.measure_option(builder=builder, runner=runner)
  14. # 为物理硬件编译
  15. if use_physical_hw:
  16.     module_loader = tvm.micro.AutoTvmModuleLoader(
  17.         template_project_dir=pathlib.Path(tvm.micro.get_microtvm_template_projects("zephyr")),
  18.         project_options={
  19. "board": BOARD,
  20. "verbose": False,
  21. "project_type": "host_driven",
  22. "serial_number": SERIAL,
  23. },
  24. )
  25.     builder = tvm.autotvm.LocalBuilder(
  26.         n_parallel=1,
  27.         build_kwargs={"build_option": {"tir.disable_vectorize": True}},
  28.         do_fork=False,
  29.         build_func=tvm.micro.autotvm_build_func,
  30.         runtime=RUNTIME,
  31. )
  32.     runner = tvm.autotvm.LocalRunner(number=1, repeat=1, timeout=100, module_loader=module_loader)
  33.     measure_option = tvm.autotvm.measure_option(builder=builder, runner=runner)
复制代码
运行主动调优​

下面在 microTVM 装备上对每个提取的任务单独运行主动调优。
  1. autotune_log_file = pathlib.Path("microtvm_autotune.log.txt")
  2. if os.path.exists(autotune_log_file):
  3.     os.remove(autotune_log_file)
  4. num_trials = 10
  5. for task in tasks:
  6.     tuner = tvm.autotvm.tuner.GATuner(task)
  7.     tuner.tune(
  8.         n_trial=num_trials,
  9.         measure_option=measure_option,
  10.         callbacks=[
  11.             tvm.autotvm.callback.log_to_file(str(autotune_log_file)),
  12.             tvm.autotvm.callback.progress_bar(num_trials, si_prefix="M"),
  13. ],
  14.         si_prefix="M",
  15. )
复制代码
为未调优的步伐计时​

为了方便比力,编译并运行不实验任何主动调优 schedule 的盘算图,TVM 会为每个算子选择一个随机调优的实现,其性能不如调优的算子。
  1. with pass_context:
  2.     lowered = tvm.relay.build(relay_mod, target=TARGET, runtime=RUNTIME, params=params)
  3. temp_dir = tvm.contrib.utils.tempdir()
  4. project = tvm.micro.generate_project(
  5. str(tvm.micro.get_microtvm_template_projects("crt")),
  6.     lowered,
  7.     temp_dir / "project",
  8. {"verbose": False},
  9. )
  10. # 为物理硬件编译
  11. if use_physical_hw:
  12.     temp_dir = tvm.contrib.utils.tempdir()
  13.     project = tvm.micro.generate_project(
  14. str(tvm.micro.get_microtvm_template_projects("zephyr")),
  15.         lowered,
  16.         temp_dir / "project",
  17. {
  18. "board": BOARD,
  19. "verbose": False,
  20. "project_type": "host_driven",
  21. "serial_number": SERIAL,
  22. "config_main_stack_size": 4096,
  23. },
  24. )
  25. project.build()
  26. project.flash()
  27. with tvm.micro.Session(project.transport()) as session:
  28.     debug_module = tvm.micro.create_local_debug_executor(
  29.         lowered.get_graph_json(), session.get_system_lib(), session.device
  30. )
  31.     debug_module.set_input(**lowered.get_params())
  32. print("########## Build without Autotuning ##########")
  33.     debug_module.run()
  34. del debug_module
复制代码
输出结果:
  1. /workspace/python/tvm/driver/build_module.py:268: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  2. "target_host parameter is going to be deprecated. "
  3. ########## Build without Autotuning ##########
  4. Node Name                                     Ops                                           Time(us)  Time(%)  Shape              Inputs  Outputs  Measurements(us)
  5. ---------                                     ---                                           --------  -------  -----              ------  -------  ----------------
  6. tvmgen_default_fused_nn_contrib_conv2d_NCHWc  tvmgen_default_fused_nn_contrib_conv2d_NCHWc  310.0 98.73 (1, 2, 10, 10, 3) 2 1 [310.0]
  7. tvmgen_default_fused_layout_transform_1       tvmgen_default_fused_layout_transform_1       3.031 0.965 (1, 6, 10, 10) 1 1 [3.031]
  8. tvmgen_default_fused_layout_transform         tvmgen_default_fused_layout_transform         0.958 0.305 (1, 1, 10, 10, 3) 1 1 [0.958]
  9. Total_time                                    -                                             313.988   -        -                  -       -        -
复制代码
为调优步伐计时​

主动调优完成后,用 Debug Runtime 为整个步伐的实验计时:
  1. with tvm.autotvm.apply_history_best(str(autotune_log_file)):
  2. with pass_context:
  3.         lowered_tuned = tvm.relay.build(relay_mod, target=TARGET, runtime=RUNTIME, params=params)
  4. temp_dir = tvm.contrib.utils.tempdir()
  5. project = tvm.micro.generate_project(
  6. str(tvm.micro.get_microtvm_template_projects("crt")),
  7.     lowered_tuned,
  8.     temp_dir / "project",
  9. {"verbose": False},
  10. )
  11. # 为物理硬件编译
  12. if use_physical_hw:
  13.     temp_dir = tvm.contrib.utils.tempdir()
  14.     project = tvm.micro.generate_project(
  15. str(tvm.micro.get_microtvm_template_projects("zephyr")),
  16.         lowered_tuned,
  17.         temp_dir / "project",
  18. {
  19. "board": BOARD,
  20. "west_cmd": "west",
  21. "verbose": False,
  22. "project_type": "host_driven",
  23. "serial_number": SERIAL,
  24. "config_main_stack_size": 4096,
  25. },
  26. )
  27. project.build()
  28. project.flash()
  29. with tvm.micro.Session(project.transport()) as session:
  30.     debug_module = tvm.micro.create_local_debug_executor(
  31.         lowered_tuned.get_graph_json(), session.get_system_lib(), session.device
  32. )
  33.     debug_module.set_input(**lowered_tuned.get_params())
  34. print("########## Build with Autotuning ##########")
  35.     debug_module.run()
  36. del debug_module
复制代码
输出结果:
  1. /workspace/python/tvm/driver/build_module.py:268: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  2. "target_host parameter is going to be deprecated. "
  3. ########## Build with Autotuning ##########
  4. Node Name                                     Ops                                           Time(us)  Time(%)  Shape              Inputs  Outputs  Measurements(us)
  5. ---------                                     ---                                           --------  -------  -----              ------  -------  ----------------
  6. tvmgen_default_fused_nn_contrib_conv2d_NCHWc  tvmgen_default_fused_nn_contrib_conv2d_NCHWc  193.2 98.657 (1, 6, 10, 10, 1) 2 1 [193.2]
  7. tvmgen_default_fused_layout_transform_1       tvmgen_default_fused_layout_transform_1       1.778 0.908 (1, 6, 10, 10) 1 1 [1.778]
  8. tvmgen_default_fused_layout_transform         tvmgen_default_fused_layout_transform         0.851 0.435 (1, 3, 10, 10, 1) 1 1 [0.851]
  9. Total_time                                    -                                             195.83    -        -                  -       -        -
复制代码
下载 Python 源代码:micro_autotune.py
下载 Jupyter notebook:micro_autotune.ipynb
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表