犀牛鸟 2026 研究笔记 estelledc.github.io

TNN 深度解读

“ncnn 的架构翻新版——用双层抽象换来多后端可扩展性”


一句话定位

TNN 是腾讯优图实验室开源的轻量级推理框架,定位为 ncnn 的继任者,在保留轻量基因的同时引入 BaseLayer/LayerAcc 双层算子抽象和 AbstractDevice 设备抽象,统一了 OpenCL/Metal/CUDA/NPU 多后端管理。

设计哲学上最精彩的地方

TNN 最精彩的设计是对 ncnn 单类 Layer 的结构性拆分——将一个”什么都做”的 Layer 切成两个职责清晰的角色:

BaseLayer 只做 shape 推断(InferOutputShape()),是平台无关的。不管模型最终跑在 ARM 还是 OpenCL 上,shape 推断逻辑只写一份。LayerAcc(AbstractLayerAcc)只做平台特定的计算实现,Init() / Reshape() / Forward() 三个接口。

这像是厨房里的分工:一个人(BaseLayer)只看菜谱算食材用量,另一个人(LayerAcc)只负责做菜。算食材的人不关心你用的是煤气灶还是电磁炉,做菜的人不用自己去数几碗米。ncnn 是一个大厨从头到尾全包,TNN 是流水线分工

分工带来的直接收益:新增后端只需写 LayerAcc,shape 逻辑零重复。以 Convolution 为例——ConvLayer(BaseLayer)只有一个 InferOutputShape();ArmConvLayerAcc 内部再通过工厂选择 1x1/3x3 Winograd/depthwise 等具体实现;OpenCLConvLayerAcc 独立选择自己的最优策略。两个后端共享 100% 的 shape 逻辑,但计算实现完全独立

Blob 设计——描述与句柄分离

TNN 的 Blob 将”这是什么数据”(BlobDesc)和”数据在哪”(BlobHandle)拆成两个独立结构。BlobDesc 携带 DeviceType、DataType、DataFormat、dims 四维信息;BlobHandle 只有裸指针 + 偏移量。Blob 自身不拥有内存,生命周期由 BlobManager 通过内存池统一管理。

DataFormat 的丰富性是 TNN 的亮点:NC4HW4(ARM 主用)、NC8HW8(ARM fp16,8 通道打包利用更宽的 NEON fp16 指令)、NHC4W4(OpenCL image2d 最优布局)。不同设备自动使用不同的最优布局,BlobConverter 负责在用户接口的 Mat(始终 NCHW)和内部 Blob 之间透明转换。

ConstFolder——预计算的巧思

TNN 有一个不起眼但实用的优化:ConstFolder(常量折叠)。Instance 初始化时会先创建一个 ConstFolder 网络,预计算所有常量子图,将结果注入主网络。运行时这些子图完全不执行。通过 DataFlag::CHANGE_NEVER 标记哪些 blob 是常量。这比 ncnn 的”无独立图优化”要精细,但比 Paddle-Lite 的 50+ MIR pass 轻量得多——恰好在”极简”和”重量级”之间找到了平衡点

局限性与场景边界

TNN 的双层抽象增加了一层间接调用,调试时需要同时追踪 BaseLayer 和 LayerAcc 两个注册表。顺序执行策略(for (auto layer : layers_) layer->Forward())没有 ncnn 的按需递归灵活——所有层都会执行,即使输出未被使用。社区活跃度(4.5K star)低于 ncnn(22K),文档和第三方资源相对稀缺。没有端侧训练和 LLM 推理支持。

本地代码结构

TNN/
  source/tnn/
    core/
      tnn_impl.h/cpp          # TNNImpl 模型解析入口
      instance.h/cpp           # Instance 推理实例
      default_network.h/cpp    # DefaultNetwork 顺序执行
      blob.h/cpp               # Blob 数据容器
      abstract_device.h        # Device 抽象接口
    layer/
      base_layer.h/cpp         # BaseLayer(shape 推断)
      conv_layer.h/cpp         # Convolution shape 逻辑
    device/
      arm/
        acc/                   # ARM LayerAcc 实现
          arm_conv_layer_acc.cpp
      opencl/
        acc/                   # OpenCL LayerAcc 实现
      metal/
        acc/                   # Metal LayerAcc 实现
      cuda/
        acc/                   # CUDA LayerAcc 实现
    interpreter/               # 模型加载与解析
    optimizer/                 # NetOptimizer 图优化
    utils/
      blob_converter.h/cpp     # Mat <-> Blob 布局转换
  tools/
    convert2tnn/               # 模型转换工具

本地关键文件

文件 用途
source/tnn/core/blob.h Blob = BlobDesc + BlobHandle,不拥有内存
source/tnn/layer/base_layer.h BaseLayer 基类,InferOutputShape() 平台无关
source/tnn/core/abstract_device.h AbstractDevice 接口,统一多后端管理
source/tnn/core/default_network.cpp DefaultNetwork 顺序执行逻辑 + ConstFolder
source/tnn/device/arm/acc/arm_conv_layer_acc.cpp ARM 卷积加速器,含 Winograd/depthwise 工厂
source/tnn/utils/blob_converter.cpp NCHW Mat 与内部 Blob 布局的转换
source/tnn/core/instance.cpp Instance 生命周期管理