ncnn加速, 不同于模型量化压缩, 而是采用另一种加速技巧.例如下面的几种:
- 使用低精度
例如: caffe2ncnn.cpp 中代码
// convert float to half precision floating point
static unsigned short float2half(float value)
{
// 1 : 8 : 23
union
{
unsigned int u;
float f;
} tmp;
tmp.f = value;
// 1 : 8 : 23
unsigned short sign = (tmp.u & 0x80000000) >> 31;
unsigned short exponent = (tmp.u & 0x7F800000) >> 23;
unsigned int significand = tmp.u & 0x7FFFFF;
// fprintf(stderr, "%d %d %d\n", sign, exponent, significand);
// 1 : 5 : 10
unsigned short fp16;
if (exponent == 0)
{
// zero or denormal, always underflow
fp16 = (sign << 15) | (0x00 << 10) | 0x00;
}
else if (exponent == 0xFF)
{
// infinity or NaN
fp16 = (sign << 15) | (0x1F << 10) | (significand ? 0x200 : 0x00);
}
else
{
// normalized
short newexp = exponent + (- 127 + 15);
if (newexp >= 31)
{
// overflow, return infinity
fp16 = (sign << 15) | (0x1F << 10) | 0x00;
}
else if (newexp <= 0)
{
// underflow
if (newexp >= -10)
{
// denormal half-precision
unsigned short sig = (significand | 0x800000) >> (14 - newexp);
fp16 = (sign << 15) | (0x00 << 10) | sig;
}
else
{
// underflow
fp16 = (sign << 15) | (0x00 << 10) | 0x00;
}
}
else
{
fp16 = (sign << 15) | (newexp << 10) | (significand >> 13);
}
}
return fp16;
}
上面代码转化为半精度浮点数类型, 还有浮点数转化8bit量化为加速等.
- 采用openmp多线程加速
#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];
}
}
并行的粒度是通道级别的或者是行级别的.
- 采用simd指令集
参考源代码sse_mathfun.h