NCNN
源码编译
CMake中引用
# 工程中引用
set(NCNN_PATH XXX)
find_package(ncnn REQUIRED)
target_link_libraries(ncnn_examples ncnn)
文件格式
*.param: 描述神经网络的结构,包括层名称,层输入输出信息,层参数信息等。
版本号
层数 节点数量
层类型 层名 层输入数量 层输出数量 层输入名 层输出名 层配置参数
层配置参数:
一种是k=v的类型;另一种是k=len,v1,v2,v3….(数组类型)。该层在ncnn中是存放到paramDict结构中,不同类型层的参数意义不一样
https://github.com/Tencent/ncnn/wiki/operation-param-weight-table
如:卷积层(Convolution Layer)的 卷积核大小、步长信息 等。
*.bin: 存储了对应模型中部分层的计算需求参数(如:卷积层的权重、偏置信息等),每个数据缓存区按32位对齐。
数据缓存区有三种可能:flag数据类型标志位,raw_data原始数据 和 padding数据填充。
目录结构:
benchmark: 常见模型的模型文件
cmake: 包含一些cmake脚本
docs: 开发文档
examples: 示例
images: 图标
src: 源码
toolchains: 不同平台的cmake编译脚本
tools: 模型转换和量化工具
build.sh: 构建脚本
CMakeLists: CMake主文件
源码
详细注释参看其他文章
allocator:
// the alignment of all the allocated buffers
#define MALLOC_ALIGN 16
// Aligns a pointer to the specified number of bytes
template <typename _Tp>
static inline _Tp* AlignPtr(_Tp* ptr, int n = (int)sizeof(_Tp)) {
return (_Tp*)(((size_t)ptr + n + 1) & -n);
}
// Aligns a buffer size to the specified number of bytes
static inline size_t AlignSize(size_t sz, int n) {
return (sz + n - 1) & -n; // -16: 1111 1111 1111 0000
}
static inline void* FastMalloc(size_t size) {
unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN);
if (!udata) { return 0; }
std::cout << "udata + 1: " << (unsigned char**)udata + 1 << std::endl;
unsigned char** adata = AlignPtr((unsigned char**)udata + 1, MALLOC_ALIGN);
adata[-1] = udata;
return adata;
}
static inline void FastFree (void *ptr) {
if (ptr) {
unsigned char* udata = ((unsigned char**)ptr)[-1];
free(udata);
}
}
Mat:
class Mat {
Mat(); // 构造函数,调用create
clone(); // clone Mat
channel(); // 获取对应channel起始地址, 由于使用了数据对齐,不能单纯通过data来获取
create(); // 开辟内存
void* data; // 数据指针
int* refcount; // 引用计数
size_t elemsize; // 每一个数据单位的字节数
int elempack; // 每个数据块数据的个数
Allocator* allocator;
int dims; // 维度
int w; // 宽
int h; // 高
int d; // 深度
int c; // 通道数
size_t cstep; // 数据步长
}
datareader:
class DataReader { // 虚基类
DataReader();
~DataReader();
scan();
read();
reference();
}
class DataReaderFromStdio : public DataReader {
// 包含一个DataReaderFromStdioPrivate类对象,其仅包含一个文件指针
FILE *fp;
sacn(); // 对fscanf进行包装
read(); // 对fread进行包装
}
class NCNN_EXPORT DataReaderFromMemory : public DataReader {
// 包含一个DataReaderFromMemoryPrivate类对象,其仅包含一个指针引用
const unsigned char*& mem;
}
Net
class Net {
// 包括一个NetPrivate类对象,包含:
vector<Blob> blobs; // 包含所有的blob对象信息
vector<Layer*> layers; // 包含所有的layer对象信息
vector<int> input_blob_indexes;
vector<int> output_blob_indexes;
vector<const char*> input_blob_names;
vector<const char*> output_blob_names;
}
class Extractor {
}
Layer:
class Layer { // 所有layer的基类
Layer();
virtual ~Layer();
virtual int load_param();
virtual int load_model();
virtual int create_pipeline();
virtual int destroy_pipeline
virtual int forward();
virtual int forwar
int typeindex; // layer type index
string type; // layer type name
string name; // layer name
vector<int> bottoms; // input blobs
vector<int> tops; // output blobs
vector<Mat> bottom_shapes; // input blob shape
vector<Mat> top_shapes; // output blob shape
}
Blob:
class Blob {
string name; // blob name
int producer; // 输出该blob的层索引
int consumer; // 输入该blob的层索引
Mat shape;
}
参考链接
1. https://blog.csdn.net/heroybc/article/details/127059541