Skip to content

第 1 章:NCNN 简介

1. NCNN 简介

NCNN 是一个为移动端极致优化的高性能神经网络前向计算框架。无第三方依赖,跨平台,QQ、微信等多款产品中即使用 NCNN 进行模型推理。

NCNN Logo

Logo

为什么选择像素风格的 Logo,因为 NCNN 的作者和本文的作者一样,都是 Minecraft 的忠实粉丝!

NCNN 是市场上最早的、发展比较成熟的、为移动端优化的、支持广泛硬件的神经网络部署框架。NCNN 使用 BSD-3 开源协议。

NCNN 是纯 C++ 实现,不依赖与其他第三方计算库,极其轻量。此外兼容各种平台和生态,可以说是面向未来的部署框架,其中还包含了为 ARM NEON 架构的汇编级别的优化,可以说良心至极!

2. 研发团队

NCNN 项目属于腾讯的优图实验室,NCNN 的核心贡献者是腾讯优图实验室的 nihui。目前 NCNN 也是作为腾讯的主打神经网络部署框架面向广大开发者。

nihui 是可爱的男孩子哦!!!下面她的照片(来源:https://github.com/nihui):

nihui

伴随着 NCNN 的核心作者 nihui 提出 PNNX,NCNN 更加兼容 PyTorch 生态圈,为扩展 NCNN 部署生态,提供更好的移动端部署奠定坚实的基础。

3. NCNN 的生态

支持的平台:

  • Linux
  • Windows
  • macOS
  • Raspberry Pi
  • Android
  • NVIDIA Jetson
  • iOS
  • WebAssembly
  • AllWinner D1
  • Loongson 2K1000
  • ......

支持的硬件:

  • Intel-CPU
  • Intel-GPU
  • AMD-CPU
  • AMD-GPU
  • Nvidia
  • Qcom-CPU
  • Qcom-GPU
  • ARM-CPU
  • ARM-GPU
  • Apple-CPU
  • Apple-GPU
  • ......

支持的模型:

  • caffe
  • pytorch
  • mxnet
  • onnx
  • darknet
  • keras
  • tensorflow (MLIR)
  • ......

官方极简示例代码:

cpp
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "net.h"

int main() {
    cv::Mat img = cv::imread("image.ppm", CV_LOAD_IMAGE_GRAYSCALE);
    int w = img.cols;
    int h = img.rows;

    // subtract 128, norm to -1 ~ 1
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(img.data, ncnn::Mat::PIXEL_GRAY, w, h, 60, 60);
    float mean[1] = { 128.f };
    float norm[1] = { 1/128.f };
    in.substract_mean_normalize(mean, norm);

    ncnn::Net net;
    net.load_param("model.param");
    net.load_model("model.bin");

    ncnn::Extractor ex = net.create_extractor();
    ex.set_light_mode(true);
    ex.set_num_threads(4);

    ex.input("data", in);

    ncnn::Mat feat;
    ex.extract("output", feat);

    return 0;
}

4. NCNN 的设计哲学

易用性

不仅让你能用,而且能学到东西。完全适合学习,完全可以用于创造自己的项目。包含很多简单的示例。

移植性

为什么使用 C++ 03?为了更好的移植性。最小前置知识原则。

Vulkan API?Vulkan 有更好的移植性,虽然有点难,也没有最快的。

可维护性

很容易看得懂,修改比较容易,优化代码都是可选的。

兼容性

高层 API 基本不变。

数据结构 Mat

Mat 只有三个维度 whc。为什么没有 batch?因为不需要。

每一个 channel 都会进行数据对齐,在多线程上优化效果明显。

没有类型信息,让开发者自己设定。大多数情况下都是 float32。约定大于配置。

模型文件格式

使用 .param.bin 两种文件分别表示网络模型和权重。为什么要用文本表示网络模型?让开发者可以魔改网络结构。