在ncnn群划水有一段时间了(nihui真的可爱),昨天up在群里说了一下,要重新写这个operators的文档,之前那个operation-param-weight-table有点草率。应该说这本该是一次简单的pr,奈何我没有深入阅读过ncnn的源码,正好借这次pr机会好好研究下。
废话不多说,先看看这个需求吧:
从图中可以看出,这是对op进行一些说明,分为参数和权重两类数据,ncnn的模型采用参数和权重分离的设计。那么只需要按照之前的operation-param-weight-table上的op列表以operators文档的方式补充完所有op的说明就算大功告成了。先来看看operators文档中现有的几个op,来初步理解一下参数和权重的具体意义。
先来看第一个op,absval这是计算绝对值的。我们在程序中找到这个,ncnn的所有op的实现都是在/ncnn/src/layer/下面的:
ncnn2.png直接上代码:
absval.h
#ifndef LAYER_ABSVAL_H
#define LAYER_ABSVAL_H
#include "layer.h"
namespace ncnn {
class AbsVal : public Layer
{
public:
AbsVal();
virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const;
};
} // namespace ncnn
#endif // LAYER_ABSVAL_H
absval.cpp
#include "absval.h"
namespace ncnn {
AbsVal::AbsVal()
{
one_blob_only = true;
support_inplace = true;
}
int AbsVal::forward_inplace(Mat& bottom_top_blob, const Option& opt) const
{
int w = bottom_top_blob.w;
int h = bottom_top_blob.h;
int channels = bottom_top_blob.c;
int size = w * h;
#pragma omp parallel for num_threads(opt.num_threads)
for (int q = 0; q < channels; q++)
{
float* ptr = bottom_top_blob.channel(q);
for (int i = 0; i < size; i++)
{
if (ptr[i] < 0)
ptr[i] = -ptr[i];
}
}
return 0;
}
} // namespace ncnn
从上面operators文档中我们可以看到:
- one_blob_only
- support_inplace
这两个关键字,而程序的构造函数那里恰好是:
AbsVal::AbsVal()
{
one_blob_only = true;
support_inplace = true;
}
经查资料可知别人的blog:
定义两个参数决定了输入输出的规则,one_blob_only
表示该层为单输入单输出,support_inplace
表示是否可以进行就地运算。比如说,卷积层是不能就地运算的,该方法表示可以在输入数据的基础上直接修改得到输出数据,但是卷积过程有重复部分,如果修改会对后面的计算产生影响。因此对于前向推理函数就会有两种方式,加上刚才的是否是单输入单输出,一共有四个推理函数。
// implement inference
// return 0 if success
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;
// implement inplace inference
// return 0 if success
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;
这个是Layer这个类里面的4个重载。
总之absval这个op的代码实现部分比较简单,没参数,没权重,只需要对张量的所有元素算一个绝对值就行了,即:
y = abs(x)
这样就完成了absval这个op的所有说明:
absval
y = abs(x)
- one_blob_only
- support_inplace
这里先写到这,我觉得应该每个op分一期吧,关于pr已经不那么重要了,借这次机会好好看看ncnn的代码。