OAID/Tengine项目扩展硬件后端开发指南

OAID/Tengine项目扩展硬件后端开发指南

Tengine Tengine is a lite, high performance, modular inference engine for embedded device Tengine 项目地址: https://gitcode.com/gh_mirrors/ten/Tengine

前言

在深度学习推理框架的开发中,硬件后端的扩展能力至关重要。OAID/Tengine作为一个轻量级、高性能的神经网络推理引擎,其设计理念之一就是提供强大的硬件扩展能力。本文将详细介绍如何在Tengine中添加自定义硬件后端,帮助开发者快速实现特定硬件的适配工作。

硬件后端设计理念

Tengine将所有可以运行CNN的硬件单元均视为设备(device),CPU就是其中最典型的设备。在框架设计中,设备通过ir_device_t结构体进行描述:

typedef struct device {
    const char* name;
    struct interface* interface;      // 设备调度操作接口
    struct allocator* allocator;      // 设备内存分配接口
    struct optimizer* optimizer;      // 设备优化器接口
    struct scheduler* scheduler;      // 设备调度器
    void*  privacy;                   // 设备私有数据
} ir_device_t;

这种设计将设备功能划分为多个模块,开发者可以根据实际需求选择实现哪些接口,具有很高的灵活性。

开发准备工作

1. 创建设备目录

在项目结构中,建议在source/device目录下创建以设备名称命名的文件夹。例如,如果要开发TPU设备支持,可以创建source/device/tpu目录。

2. 编写CMake构建文件

从已有设备(如ACL)复制一份CMakeLists.txt作为模板,然后进行适当修改:

# 设置源码根路径
SET(_TPU_ROOT ${CMAKE_SOURCE_DIR}/source/device/tpu)

# 添加头文件搜索路径
LIST(APPEND _DEV_TPU_HEADER_PATH ${_TPU_ROOT})
LIST(APPEND _DEV_TPU_HEADER_PATH ${CMAKE_SOURCE_DIR}/3rdparty/tpu/include)

# 添加链接库搜索路径 
LIST(APPEND _DEV_TPU_LINK_PATH ${CMAKE_SOURCE_DIR}/3rdparty/tpu/lib)

# 收集源码文件
AUX_SOURCE_DIRECTORY("${_TPU_ROOT}" _TPU_BASE_SOURCE)
LIST(APPEND _DEV_TPU_DEVICE_SOURCE ${_TPU_BASE_SOURCE})

3. 配置项目构建选项

在根目录的CMakeLists.txt中添加设备编译选项:

OPTION(TENGINE_ENABLE_TPU "Enable TPU device support" OFF)

并在source/device/CMakeLists.txt中添加相应条件编译逻辑:

IF(TENGINE_ENABLE_TPU)
    ADD_SUBDIRECTORY(tpu)
    # 添加各种路径和编译选项
ENDIF()

核心接口实现

1. 设备接口(interface)

interface结构体定义了设备的基本操作接口:

typedef struct interface {
    int (*init)(struct device* device);               // 设备初始化
    int (*pre_run)(struct device*, struct subgraph*); // 运行前准备
    int (*run)(struct device*, struct subgraph*);     // 执行推理
    int (*post_run)(struct device*, struct subgraph*);// 运行后处理
    int (*release_device)(struct device*);            // 设备释放
    // 其他可选接口...
} ir_interface_t;

典型实现示例:

static struct interface tpu_interface = {
    .init = tpu_dev_init,
    .pre_run = tpu_dev_prerun,
    .run = tpu_dev_run,
    .post_run = tpu_dev_postrun,
    .release_device = tpu_dev_release,
};

2. 分配器接口(allocator)

allocator接口用于设备能力上报和资源管理:

typedef struct allocator {
    int (*describe)(struct device*);      // 设备能力描述
    int (*evaluation)(struct subgraph*);  // 子图评估
    int (*allocate)(struct subgraph*);    // 资源分配
    int (*release)(struct subgraph*);     // 资源释放
} ir_allocator_t;

3. 优化器接口(optimizer)

optimizer接口用于图优化和切分:

typedef struct optimizer {
    int (*split_graph)(struct graph*);     // 图切分
    int (*optimize_graph)(struct graph*);  // 图优化
} ir_optimizer_t;

设备注册与注销

最后需要实现设备的注册和注销函数:

int register_tpu_device() {
    // 填充ir_device_t结构体
    static struct device tpu_device = {
        .name = "TPU",
        .interface = &tpu_interface,
        .allocator = &tpu_allocator,
        .optimizer = &tpu_optimizer,
        .scheduler = nullptr,  // 使用默认调度器
        .privacy = nullptr
    };
    
    // 调用框架注册接口
    return register_device(&tpu_device);
}

int unregister_tpu_device() {
    return unregister_device("TPU");
}

开发建议与最佳实践

  1. 渐进式开发:建议先实现最基本的interface接口,确保设备能够运行简单模型,再逐步添加其他功能。

  2. 充分利用现有实现:可以参考CPU、GPU等已有设备的实现方式,特别是内存管理和调度逻辑。

  3. 性能优化:在基础功能完成后,可以通过以下方式优化性能:

    • 实现异步执行接口
    • 优化内存分配策略
    • 添加特定算子的优化实现
  4. 调试技巧

    • 使用Tengine的日志系统输出调试信息
    • 逐步验证每个接口的功能
    • 使用小型测试模型进行验证

总结

通过本文的介绍,我们了解了在OAID/Tengine中添加自定义硬件后端的完整流程。Tengine的模块化设计使得硬件适配工作变得清晰而高效,开发者可以专注于硬件特定功能的实现,而不必关心框架的其他复杂逻辑。这种设计不仅降低了开发门槛,也为各种异构计算设备的集成提供了可能。

Tengine Tengine is a lite, high performance, modular inference engine for embedded device Tengine 项目地址: https://gitcode.com/gh_mirrors/ten/Tengine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时翔辛Victoria

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值