NCNN-Blob_Layer

NCNN-Blob_Layer

路径:src/blob.h 和 src/blob.cpp, src/layer.h 和 src/layer.cpp

Blob结构简单,源码也很短, Layer包括层的名称,参数等,层的输入输出节点信息,层的执行流程

源码

class NCNN_EXPORT Blob {
public:
    Blob();				// 构造函数为空
public:
    std::string name;	// 节点的名字
    int producer;		// 输出该节点的层索引
    int consumer;		// 输入该节点的层索引
    Mat shape;			// 节点的形状
};
这里的layer是基类,所以函数不对应任何有意义的实现,不同的层继承Layer,实现对应的虚函数
class layer	{
public:
    Layer();
    virtual ~Layer();
    virtual int load_param(const ParamDict& pd);				// 加载层参数
    virtual int load_model(const ModelBin& mb);					// 加载模型layer implementation specific setup权重
    virtual int create_pipeline(const Option& opt);				// 配置层
    virtual int destroy_pipeline(const Option& opt);			// 取消配置
    
public:
	blob one_blob_only;  // 单输入单输出,有优化
	...
	
public:
	// 执行推理
    virtual int forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const;
    virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const;

    virtual int forward_inplace(std::vector<Mat>& bottom_top_blobs, const Option& opt) const;
    virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const;
public:
	void* userdata;						// 自定义用户数据
	int typeindex;						// 层类型索引
	std::string type;					// 层类型名称
	std::string name;					// 层名称
    std::vector<int> bottoms;			// 输入节点索引
    std::vector<int> tops;				// 输出节点索引
    std::vector<Mat> bottom_shapes;		// 输入节点形状
    std::vector<Mat> top_shapes;		// 输出节点形状
}

// 两个宏定义:
// 函数指针layer_creator_func:输入为void*,输出为Layer*
typedef Layer* (*layer_creator_func)(void*);
// 函数指针layer_destroyer_func:输入为Layer* 和 void*, 无输出
typedef void (*layer_destroyer_func)(Layer*, void*);

struct layer_registry_entry {
    const char* name;				// 层名称
    layer_creator_func creator;		// 对应的工厂函数
};

struct custom_layer_registry_entry {
    const char* name;					// 层名称
    layer_creator_func creator;			// 对应的工厂函数
    layer_destroyer_func destroyer;		// 对应的工厂函数
    void* userdata;						// 用户自定义数据
};

struct overwrite_builtin_layer_registry_entry {
    int typeindex;						// 层索引
    layer_creator_func creator;			// 对应的工厂函数
    layer_destroyer_func destroyer;		// 对应的工厂函数
    void* userdata;						// 用户自定义数据
};

// DEFINE_LAYER_CREATOR(Input_final): Input_layer_creator(void* );
#define DEFINE_LAYER_CREATOR(name)                          \
    ::ncnn::Layer* name##_layer_creator(void* /*userdata*/) \
    {                                                       \
        return new name;                                    \
    }

#define DEFINE_LAYER_DESTROYER(name)                                      \
    void name##_layer_destroyer(::ncnn::Layer* layer, void* /*userdata*/) \
    {                                                                     \
        delete layer;                                                     \
    }
// 定义层的个数
static const int layer_registry_entry_count = sizeof(layer_registry) / sizeof(layer_registry_entry);
这里的layer_registry由cmake脚本文件来生成具体有多少中类型的层,
layer_registry是一个layer_registry_entry的数组,所以这里除以layer_registry_entry的大小就是层的个数
int layer_to_index(const char* type) {
    for (int i = 0; i < layer_registry_entry_count; i++) {
    	// 遍历,比较层名称,获取这个层对应于layer_registry_entry_count的索引
        if (strcmp(type, layer_registry[i].name) == 0)	
            return i;
    }

    return -1;
}

Layer* create_layer(const char* type) {
	// 通过layer name, 获取index, 转而调用create_layer(int index)
    int index = layer_to_index(type);
    if (index == -1)
        return 0;

    return create_layer(index);
}

Layer* create_layer(int index) {
    if (index < 0 || index >= layer_registry_entry_count)
        return 0;
    else {
    	layer_creator = layer_registry[index].creator;  // layer_registry_entry.creator 宏定义的函数指针
    }
    
    Layer* layer = layer_creator(0);  // 创建层
    layer->typeindex = index;  // 层的类型索引,对应是使用layer_to_index获取的索引
    return layer;
}

layer_registy.h,由cmake自动生成:

AbsVal = 0,
ArgMax = 1,
BatchNorm = 2,
Bias = 3,
BNLL = 4,
Concat = 5,
Convolution = 6,
Crop = 7,
Deconvolution = 8,
Dropout = 9,
Eltwise = 10,
ELU = 11,
Embed = 12,
Exp = 13,
Flatten = 14,
InnerProduct = 15,
Input = 16,
Log = 17,
LRN = 18,
MemoryData = 19,
MVN = 20,
Pooling = 21,
...
Fold = 95,
Unfold = 96,
GridSample = 97,
CumulativeSum = 98,
CopyTo = 99,

至于更详细的各种层如何实现对应的forward、load_param和load_model等函数,需要去看src/layers/*.cc下不同layer层的具体实现

参考

https://www.jianshu.com/p/3036c17b6b0e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值