ncnn源码阅读笔记(一)
工作需要,最近在使用ncnn,为了写自定义层,深入理解下源码,在此作个笔记。
https://github.com/Tencent/ncnn
目录结构
image.pngbenchmark:一些常见模型的模型文件,如mobilenet,resnet,vgg等。
cmake:有关链接openmp和valkan的cmake文件,这两个都是并行计算加速用的
docs:文档,包括开发指南,构建指南等等
examples:使用ncnn的示例,包括几个常用模型的cpp调用示例,及其cmakelist文件
images:此目录无关紧要,是页面上的图片
src:ncnn源码目录
toolchains:不同平台的cmake编译文件,包括aarch64、arm-linux、ios、jetson、pi3等
tools:包含以下其他深度学习框架模型转换到ncnn模型的工具,以及量化工具等
build.sh:构建脚本
CMakeLists.txt:总的cmake文件
这里我们主要阅读src中的源码
src/中的目录结构:
image.png
主要有一个layer目录,layer目录下时对应三个平台的算子(如卷积、池化等)的实现,arm下是用neon加速,vulkan下是用vulkan加速,x86下还没看,一般来说,x86下会用avx、sse或sse2加速计算。vulkan是类似opengl的存在,neon是基于arm的simd(单指令多数据)加速,avx、sse、sse2都是基于x86架构的cpu的simd加速(如需详细了解加速计算,可参考本账号下的异构并行编程文集,目前只更新了neon)。
example
首先从一个例子看起,在example目录中有几个cpp文件,这些是调用各自文件名对应模型的cpp文件,比如mobilenetssd.cpp就是以mobilenet为主干网络的ssd算法模型的调用。
- ncnn的模型调用流程
看example中的例子可以基本总结出ncnn的模型调用流程如下:
#include "net.h"
ncnn::Net xxxnet; //声明一个Net对象
ncnn::Mat in_img; //声明输入
ncnn::Mat out_img; //声明输出
xxxnet.load_param(xxx.param); //载入模型结构参数文件
xxxnet.load_model(xxx.bin); //载入模型权重参数文件
ncnn::Extractor ex = xxxnet.create_extractor(); //创建网络执行器
ex.set_num_threads(2); //设置执行器使用的线程数
ex.set_light_mode(true); //设置执行器是否使用轻量模式
ex.input("data", in_img); //设置执行器输入
ex.extract("prob", out_img); //提取执行器输出
源码的阅读也按照上面这个顺序来,结构就很清晰。
首先分析load_param的原理,再分析load_model的原理,接着分析extractor的原理。