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

ncnn 深度解读

“零依赖的手工匠人——移动端推理框架的极简先驱”


一句话定位

ncnn 是腾讯开源的零第三方依赖移动端推理框架,所有算子手写 NEON/SSE/AVX 优化,以极致轻量和 Vulkan GPU 跨平台计算为核心竞争力。22K star,移动推理领域社区最大。

设计哲学上最精彩的地方

ncnn 最精彩的设计是 elempack 动态打包。想象你在装书架:普通做法是每层放一本书(channel),但 ncnn 会根据你的书架宽度(CPU SIMD 宽度)自动决定每层并排放几本——NEON 128-bit 放 4 本,AVX 256-bit 放 8 本,AVX-512 放 16 本。这不是固定的”每层放 4 本”(NC4HW4),而是运行时自适应的打包策略

elempack 直接绑定到 Mat 数据容器的 elemsize 字段:elemsize = sizeof(标量) x elempack。当 elempack=4 且数据类型为 float32 时,每个”像素位置”存 4 个 channel 的值,恰好填满一个 128-bit 寄存器。Mat 甚至为 float32x4_t(NEON)和 __m256(AVX)提供了原生 fill() 重载。SIMD 指令集和内存布局的绑定在数据结构层面完成,而非在每个算子内部手动处理,这是 ncnn 性能的根基。

第二个精彩设计是按需递归调度(Lazy Evaluation)。ncnn 不按拓扑序顺序执行所有 Op,而是从用户请求的输出 blob 反向递归计算依赖链——未被依赖的层完全不执行。配合 Light mode(中间 blob 消费后立即释放),在只需要部分输出的场景下内存占用极低。这像是”你问我答”模式:你只问了最后一道菜的做法,我只教你这道菜需要的步骤,不把整本菜谱从头念到尾。

Vulkan GPU 后端——独一份的跨平台方案

ncnn 是六个主流移动推理框架中唯一选择 Vulkan Compute Shader 作为 GPU 后端的。其他框架(MNN/TNN/MACE/Paddle-Lite)都选了 OpenCL 或 Metal,而 Vulkan 的优势是跨 Android/Windows/Linux/macOS 全平台——一套 GLSL Compute Shader 代码覆盖所有 GPU 厂商。

每个算子有多个 .comp shader 变体(按 packing/算法/数据类型组合),编译为 SPIR-V 嵌入二进制。VkCompute 录制命令、Pipeline 封装 shader dispatch,最终 submit_and_wait() 提交执行。代价是需要手写 GLSL shader,门槛较高,但一旦写好,可移植性远超 OpenCL。

单类继承的算子设计——简单到极致

ncnn 的 Layer 基类是六个引擎中最简单的算子抽象:load_param / load_model / create_pipeline / forward,一个类搞定全部。平台特化通过继承:Convolution -> Convolution_arm -> 内部按 NEON/fp16/int8 分支。Vulkan 版通过 Convolution_vulkan 独立继承。

编译时 CMake 自动生成分层注册表(通用 -> ARM/x86 基础 -> AVX -> AVX-512 -> Vulkan),运行时从最高能力注册表逐级回退。Shape 推断和计算实现耦合在同一个类中——这是 ncnn 和后继者 TNN 最大的架构差异(TNN 拆成了 BaseLayer + LayerAcc 双层)。

局限性

ncnn 不支持 NPU 加速(无 NNAPI/CoreML/Hexagon 集成),没有端侧训练能力,LLM 推理依赖社区方案。图优化管线极简——没有独立的 pass 系统,融合策略有限。这些都是”极简”路线的代价:每增加一个后端就要写完整的 Layer 子类,工程复杂度随后端数量线性增长

本地代码结构

ncnn/
  src/
    mat.h / mat.cpp          # 核心数据容器(elempack)
    layer.h / layer.cpp       # Layer 基类
    net.h / net.cpp           # Net 推理调度 + Extractor
    layer/                    # 通用 Layer 实现
      convolution.h/cpp
      pooling.h/cpp ...
    layer/arm/                # ARM NEON 特化
      convolution_arm.cpp
    layer/x86/                # x86 SSE/AVX 特化
    layer/vulkan/             # Vulkan GPU 实现
      convolution_vulkan.cpp
      convolution_*.comp      # GLSL compute shader
    gpu.h / command.h         # Vulkan 调度基础设施
    pipeline.h                # Vulkan pipeline 封装
  tools/
    onnx2ncnn.cpp             # ONNX 转换器
    caffe2ncnn.cpp            # Caffe 转换器

本地关键文件

文件 用途
src/mat.h Mat 数据容器定义,elempack/elemsize/cstep 核心字段
src/layer.h Layer 基类,forward/load_param 接口定义
src/net.h Net 推理调度,按需递归 + Light mode
src/layer/arm/convolution_arm.cpp ARM NEON 卷积实现,Winograd/im2col/GEMM 策略
src/layer/vulkan/convolution_vulkan.cpp Vulkan 卷积实现 + shader 管理
src/gpu.h Vulkan 设备抽象和能力检测
tools/onnx2ncnn.cpp ONNX 到 ncnn 格式的模型转换工具