【Tengine端侧推理框架】——注册机制(一)

7 篇文章 1 订阅
4 篇文章 0 订阅

code:https://github.com/OAID/Tengine
图片,代码都来自以上项目。
在这里插入图片描述

1. 简介

Tengine 由 OPEN AI LAB 主导开发,该项目实现了深度学习神经网络模型在嵌入式设备上的快速、高效部署需求。为实现在众多 AIoT 应用中的跨平台部署,本项目使用 C 语言进行核心模块开发,针对嵌入式设备资源有限的特点进行了深度框架裁剪。同时采用了完全分离的前后端设计,有利于 CPU、GPU、NPU 等异构计算单元的快速移植和部署,降低评估、迁移成本。

2. Content

因为Tengine是由C语言开发的,和ncnn,mnn等用C++开发的框架有一定的区别。因为只能用函数,所以op,serializer(模型解析器)等的注册都是要在程序的时候进行的。而且对op,serializer等组织需要使用函数指针来模拟C++的多态性

这里对op的注册机制进行解读。

首先给出数据结构之间的关系图:
在这里插入图片描述

2.1 流程

这里只是对op_methodop_name的注册梳理,以absval的注册为例

  • 定义好absvalop_methodop_name
struct method m;
m.version = 1;
m.init = init_op;               // 函数指针
m.release = release_op;         // 函数指针

return register_op(OP_ABSVAL, OP_ABSVAL_NAME, &m); 
  • 初始化static vector_t* internal_op_method_registrystatic vector_t* internal_op_name_registry这里可以就着上面的关系图进行梳理

这里最外面的容器是vector_t, 然后vector_tmem才是指向注册数据的位置。mem指向8个vector_entry_t空间(初始为8个,如果不够了按8个递增申请),valid指示数据是否写入,这里的unsigned char data[]指明methodop_name在内存的初始位置。后面在使用的时候,就在internal_op_method_registryinternal_op_name_registry去找。

    vector_t* v = (vector_t*)sys_malloc(sizeof(vector_t));

    if (v == NULL)
    {
        return NULL;
    }

    v->elem_num = 0;
    v->elem_size = elem_size;
    v->free_func = free_data;
    v->entry_size = align(elem_size + (int)sizeof(vector_entry_t), TE_VECTOR_ALIGN_SIZE);   // 32, 要写入的数据 字节数

    v->ahead_num = 8;               // 为什么有8个空间, 以8的倍数进行拓展

    v->space_num = v->ahead_num;

    v->real_mem = sys_malloc(v->entry_size * v->space_num + TE_VECTOR_ALIGN_SIZE);      // 32*8+8
    v->mem = align_address(v->real_mem, TE_VECTOR_ALIGN_SIZE);                          // align = 8, 对申请的内存进行 8 字节对齐

    for (int i = 0; i < v->space_num; i++)
    {
        vector_entry_t* e = get_vector_entry(v, i);         // 前面放 vector_entry_t
        e->valid = 0;               // 是否写入的标志位
    }

    return v;
  • 注册op_name
    下面的 push_vector_data , 会用 memcpy 把栈上的数据内容 copy 到已申请的堆内存上memcpy(e->data, data, v->elem_size);
    ir_op_name_entry_t op_map;

    op_map.type = type;
    op_map.name = name;

    return push_vector_data(internal_op_name_registry, &op_map);        // 写入数据,如果
  • 同理注册method
    这里在注册前会internal_op_method_registry遍历,看是否已经注册
static int register_op_registry(ir_method_t* method)
{
    if (find_op_method(method->type, method->version))          // 遍历检查是否已经注册
    {
        return -1;
    }

    return push_vector_data(internal_op_method_registry, method);
}

总结

  • 总结起来就是把各个opir_method_t数据保存到internal_op_method_registryir_op_name_entry_t数据保存到internal_op_name_registry
  • 对照着上面的数据关系图来梳理
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值