tvm如何添加npu支持

本文档详细介绍了如何在TVM中为ethos硬件添加NPU支持,包括环境配置、get_pattern_table、MergeComposite、AnnotateTarget等步骤。通过对TVM编译流程的分析,展示了从模型转换到生成针对ethos-n的代码的过程,为添加自定义NPU硬件支持提供了指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


TVM算是比较大的社区,用的小伙伴很多,效果也不错,知乎上有很多关于TVM stack relay流程的分析,现在自行设计AI硬件的公司很多,包括研究所,但是没有关于添加自定义硬件的帖子(也有可能是我没搜到 -!),所以我接下来介绍下怎么添加自定义硬件。

为方便大家对流程理解和实操,我以ethos这个硬件来写,阅读的时候需要关注一下源码里面的中文说明

Tips: 实话实说,在下文笔不好,但尽量把关键点都写错来。

代码准备

我用的TVM版本是0.7,对应ethos stack的版本是20.5,这里版本必须对应,因为ethos stack在新版本中把部分class定义改了,不能一次编过。

tvm 环境

tvm 的环境我这里就不写了,网上一大堆教程

ethos stack

  • 下载 ethos stack
    1.从github下载
    git clone https://github.com/Arm-software/ethos-n-driver-stack ethos-stack
    2.从gitee 镜像下载,这个下载比较快;
    git clone https://gitee.com/mirrors_ARM-software/ethos-n-driver-stack.git ethos-stack
  • 安装一些依赖
sudo apt install git scons make sparse  gcc bc \
    gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
  • 切换到对应版本,并创建自己的branch
    cd  ethos-stack
    git checkout 20.05
    git branch mydev
    git checkout mydev
  • 编译
    我这里在host开发,所以不用交叉编译方式
  1. 复制 ethosn.bin 到host
    cd ethos-stack
    sudo cp firmware/ethosn.bin /lib/firmware/
  1. 编译ko和insmod
    cd ethos-stack/kernel-module 
    make -C /usr/src/linux-headers-4.15.0-136-generic M=$PWD  EXTRA_CCFLAGS=" -DETHOSN_NS" modules
    

linux-headers-4.15.0-136-generic是我当前系统的源码路径,你可以用’uname -a’ 查看你当前的源码版本
EXTRA_CCFLAGS=" -DETHOSN_NS" 表示使用非安全模式
编译完成后会在当前目录生成ethosn.ko
接下来就是加载驱动到系统

    sudo insmod ethosn.ko

Tips:
ethosn.ko加载后,会查找device,如果匹配会创建 /dev/ethosn0 这个设备节点。然后runtime会访问这个设备节点,当然在host设备上是没有这个设备节点的,因为host上没有ethosn的硬件。当然我没可以修改ethos-stack/kernel-module 这个驱动,以实现一个假的npu,在insmod ethosn.ko是能生成/dev/ethons0这个设备节点。甚至实现驱动里面的ioctl功能。
3. 编译ethos-driver

    cd ethos-stack/ethosn-driver/driver
    scons install_prefix=<install_directory> install

install_directory 就是driver编译完成后放到哪里,
比如

    scons install_prefix=/home/xxx/opt/arm/ethosn-driver install

相信大家在编译TVM的时候,在config.make的时候看到过下面这段话

# Whether to build with Arm Ethos-N support
# Possible values:
# - OFF: disable Arm Ethos-N support
# - path/to/arm-ethos-N-stack: use a specific version of the
#   Ethos-N driver stack
set(USE_ETHOSN OFF)

没错,如果你要使用ethos,这里可以改成

set(USE_ETHOSN /home/xxx/opt/arm/ethosn-driver)

relay.build for ethosn

接下来梳理ethos npu的build流程,理解了此流程,离添加自己的加速器硬件支持就更进一步了。

先来看个测试代码

# 源码见 "<tvm_path>/tests/python/contrib/test_ethosn/test_networks.py"
def _test_image_network(
    model_url,    model_sub_path,    input_dict,    compile_hash,
    output_count,    host_ops=0,    npu_partitions=1,    run=False,
):
    if not ethosn_available():
        return

    def get_model():
        if model_url[-3:] in ("tgz", "zip"):
            model_path = tf_testing.get_workload_official(
                model_url,
                model_sub_path,
            )
        else:
            model_path = download.download_testdata(
                model_url,
                model_sub_path,
            )
        return _get_tflite_model(model_path, input_dict, "uint8")

    inputs = {
   
   }
    for input_name in input_dict:
        input_shape = input_dict[input_name]
        inputs[input_name] = tei.get_real_image(input_shape[1], input_shape[2])
    str = print(input_shape)

    mod, params = get_model()
    m = tei.build(mod, params, npu=True, expected_host_ops=host_ops,
                  npu_partitions=npu_partitions)#这里调用的下面的build函数
    tei.assert_lib_hash(m.get_lib(), compile_hash)
    if run:
        tei.run(m, inputs, output_count, npu=True)

上面这个函数调用的几个重要接口是get_model,tei.build以及tei.run。
get_model的功能就是调用frontend模块,将各种框架的model和weight映射成TVM IR格式。
tei.build 正如其字面意思build,实现optimize和compile,调用的是下面这个build的函数。
tei.run 就是把build输出的结果加载到runtime执行inference。

# 源码见 "<tvm_path>/tests/python/contrib/test_ethosn/infrastructure.py"
def build(mod, params, npu=True, expected_host_ops=0, npu_partitions=1):
    """Build a network with or without Ethos-N offloading.
    """
    relay.backend.compile_engine.get().clear()
    with tvm.transform.PassContext(
        opt_level=3, config={
   
   "relay.ext.ethos-n.options": {
   
   "variant": 0}}
    ):
        with tvm.target.Target("llvm"):
            if npu:
                f = relay.build_module.bind_params_by_name(mod["main"], params)
                mod = tvm.IRModule()
                mod["main"] = f
                # step 1
                pattern = get_pattern_table("ethos-n")
                # step 2
                mod = relay.transform.MergeComposite(pattern)(mod)
                mod = relay.transform.AnnotateTarget("ethos-n")(mod)
                # step 3
                mod = relay.transform.MergeCompilerRegions()(mod)
                mod = relay.transform.PartitionGraph()(mod)
                host_op_count = get_host_op_count(mod)
                assert (
                    host_op_count == expected_host_ops
                ), "Got {} h
<think>好的,我现在需要帮用户解答关于TVM后端开发的问题。首先,用户提到了想了解相关的指南、技术文档和教程,我得先回想一下系统提供的引用内容。 引用[1]提到了Apache TVM中文文档项目,这可能是一个重要的资源。用户可以通过参与这个项目深入了解技术细节,所以应该推荐这个中文文档。另外,引用[4]讨论了TVM后端开发中驱动API的使用、线程安全处理以及PackedFunc的作用,这些都是后端开发的关键点,需要详细说明。 接下来,我需要组织回答的结构,确保符合用户的要求:结构清晰,分步骤解决问题。可能需要分为几个部分,比如核心概念、开发步骤、参考资料等。 然后,根据用户提供的引用内容,特别是引用[4],需要解释驱动胶水层的实现、线程安全处理、PackedFunc的应用,以及硬件抽象层(HAL)。这些都是后端开发的重要部分,必须涵盖到。 同时,用户可能需要具体的代码示例,但根据引用[2],TVM的API类似numpy,但数据结构是tvm.IRModule,所以可能需要提到如何使用这些API进行开发,但具体代码可能需要参考文档。 另外,用户可能需要了解如何参与社区和获取更多资源,引用[1]和[3]提到了中文文档和华为昇腾的培训,可以推荐这些资源。 需要确保回答使用中文,数学公式正确应用$...$和$$...$$格式,但问题中可能较少涉及数学,不过如果有性能分析或算法部分,可能需要使用。但当前问题更多是关于开发指南,可能数学公式较少,但需注意其他LaTeX格式的正确性。 最后,生成相关问题,考虑用户可能进一步想知道优化方法、调试工具、硬件支持等,所以相关问题可以围绕这些方面。</think>### TVM 后端开发指南 TVM(Tensor Virtual Machine)的后端开发主要涉及硬件适配与优化,其核心在于**硬件抽象层(HAL)**的实现和**驱动胶水层**的编写。以下是开发的关键步骤与技术要点: --- #### 1. **驱动胶水层开发** - **驱动API集成**:TVM支持多类型硬件设备,需通过驱动API加载Kernel、设置参数并启动计算。例如,使用C++实现驱动接口的封装,确保跨平台兼容性[^4]。 - **线程安全处理**:通过修补驱动API,暴露线程安全的函数,避免多线程环境下的资源竞争问题。 - **PackedFunc应用**:利用TVM的`PackedFunc`机制,统一函数调用接口,减少适配不同类型硬件的代码冗余。 --- #### 2. **硬件抽象层(HAL)实现** - **硬件特性映射**:将TVM的中间表示(IR)转换为目标硬件的指令集,例如GPU的CUDA或NPU的专用指令。 - **内存管理**:优化内存分配策略,支持零拷贝数据传输或硬件特定的内存布局(如纹理内存)。 - **性能调优**:通过AutoTVM或Ansor等工具自动搜索最优的Kernel参数(如线程块大小、循环展开策略)。 --- #### 3. **开发流程示例** 1. **定义目标设备**:在TVM中注册新硬件目标(如`Target("my_hardware")`)。 2. **实现运行时模块**:继承`runtime::Module`类,重载`GetFunction`方法以支持硬件特定的Kernel调用。 3. **编译与部署**:使用`tvm.build`生成可执行模块,并通过TVM运行时加载执行。 ```python # 示例:自定义硬件运行时模块 class MyHardwareModule(runtime.Module): def __init__(self, kernel_func): self.kernel_func = kernel_func def get_function(self, name): if name == "my_kernel": return self.kernel_func ``` --- #### 4. **学习资源与工具** - **TVM中文文档**:包含后端开发的详细API说明和案例,适合从基础到进阶学习[^1]。 - **昇腾智算技术研修**:华为昇腾提供的NPU开发课程,涵盖TVM在异构计算中的应用[^3]。 - **社区贡献**:通过参与TVM开源项目(如新增硬件后端),实践驱动开发与优化技巧。 ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值