170 lines
7.0 KiB
ReStructuredText
170 lines
7.0 KiB
ReStructuredText
AdderFusion
|
||
=================
|
||
|
||
Adder是一种卷积替代算子,它使用L1距离度量(绝对差的和)代替传统卷积中的点积操作。与标准卷积不同,Adder通过计算特征与卷积核之间的绝对差的负和来进行特征提取。假定输入X,filter表示为F,它按以下公式计算:
|
||
|
||
.. math::
|
||
|
||
Y(m,n,t) = - \sum_{i=0}^{d} \sum_{j=0}^{d} \sum_{k=0}^{C_{in}} |X(m+i, n+j, k) - F(i,j,k,t)|
|
||
|
||
输入:
|
||
- **input_x** - 输入数据的地址
|
||
- **input_w** - 输入卷积核权重的地址
|
||
- **bias** - 输入偏置的地址
|
||
- **conv_param** - 算子计算所需参数的结构体,类型为 ``ConvParameter``。其各成员见下述。
|
||
- **core_mask** - 核掩码(仅适用于共享存储版本)。
|
||
|
||
输出:
|
||
- **out_y** - 输出地址。
|
||
|
||
**ConvParameter定义:**
|
||
|
||
.. code-block:: c
|
||
:linenos:
|
||
|
||
typedef struct ConvParameter {
|
||
void* workspace_; // 用于存放中间计算结果
|
||
int output_batch_; // 输出数据总批次
|
||
int input_batch_; // 输入数据总批次
|
||
int input_h_; // 输入数据h维度大小
|
||
int input_w_; // 输入数据w维度大小
|
||
int output_h_; // 输出数据h维度大小
|
||
int output_w_; // 输出数据w维度大小
|
||
int input_channel_; // 输入数据通道数
|
||
int output_channel_; // 输出数据通道数
|
||
int kernel_h_; // 卷积核h维度大小
|
||
int kernel_w_; // 卷积核w维度大小
|
||
int group_; // 组数
|
||
int pad_l_; // 左填充大小
|
||
int pad_u_; // 上填充大小
|
||
int dilation_h_; // 卷积核h维度膨胀尺寸大小
|
||
int dilation_w_; // 卷积核w维度膨胀尺寸大小
|
||
int stride_h_; // 卷积核h维度步长
|
||
int stride_w_; // 卷积核w维度步长
|
||
int buffer_size_; // 为分块计算所分配的缓存大小
|
||
} ConvParameter;
|
||
|
||
支持平台:
|
||
``FT78NE``
|
||
``MT7004``
|
||
|
||
.. note::
|
||
- FT78NE 支持int8, fp32
|
||
- MT7004 支持fp16, fp32
|
||
|
||
**共享存储版本:**
|
||
|
||
.. c:function:: void i8_adder_s(int8_t* input_x, int8_t* input_w, int8_t* out_y, int* bias, ConvParameter *conv_param, int core_mask)
|
||
.. c:function:: void hp_adder_s(half* input_x, half* input_w, half* out_y, half* bias, ConvParameter *conv_param, int core_mask)
|
||
.. c:function:: void fp_adder_s(float* input_x, float* input_w, float* out_y, float* bias, ConvParameter *conv_param, int core_mask)
|
||
|
||
**C调用示例:**
|
||
|
||
.. code-block:: c
|
||
:linenos:
|
||
:emphasize-lines: 32
|
||
|
||
void TestAdderSMCFp32(int* input_shape, int* weight_shape, int* output_shape, int* stride, int* padding, int* dilation, int groups, float* bias, int core_mask) {
|
||
int core_id = get_core_id();
|
||
int logic_core_id = GetLogicCoreId(core_mask, core_id);
|
||
int core_num = GetCoreNum(core_mask);
|
||
float* input_data = (float*)0x88000000;
|
||
float* weight = (float*)0x89000000;
|
||
float* output_data = (float*)0x90000000;
|
||
float* bias_data = (float*)0x91000000;
|
||
ConvParameter* param = (ConvParameter*)0x92000000;
|
||
if (logic_core_id == 0) {
|
||
memcpy(bias_data, bias, sizeof(float) * output_shape[3]);
|
||
param->dilation_h_ = dilation[0];
|
||
param->dilation_w_ = dilation[1];
|
||
param->group_ = groups;
|
||
param->input_batch_ = input_shape[0];
|
||
param->input_h_ = input_shape[1];
|
||
param->input_w_ = input_shape[2];
|
||
param->input_channel_ = input_shape[3];
|
||
param->kernel_h_ = weight_shape[1];
|
||
param->kernel_w_ = weight_shape[2];
|
||
param->output_batch_ = output_shape[0];
|
||
param->output_h_ = output_shape[1];
|
||
param->output_w_ = output_shape[2];
|
||
param->output_channel_ = output_shape[3];
|
||
param->stride_h_ = stride[0];
|
||
param->stride_w_ = stride[0];
|
||
param->pad_u_ = padding[0];
|
||
param->pad_l_ = padding[2];
|
||
param->workspace_ = (float*)0x10000000;
|
||
}
|
||
sys_bar(0, core_num);
|
||
fp_adder_s(input_data, weight, output_data, bias_data, param, core_mask);
|
||
}
|
||
|
||
void main(){
|
||
int in_channel = 4;
|
||
int out_channel = 4;
|
||
int groups = 4;
|
||
int input_shape[4] = {1, 30, 30, in_channel}; // NHWC
|
||
int weight_shape[4] = {out_channel, 3, 3, in_channel / groups};
|
||
int output_shape[4] = {1, 10, 10, out_channel}; // NHWC
|
||
int stride[2] = {2, 2};
|
||
int padding[4] = {1, 1, 1, 1};
|
||
int dilation[2]= {2, 2};
|
||
float bias[4] = {0, 0, 0, 0};
|
||
int core_mask = 0b1111;
|
||
TestAdderSMCFp32(input_shape, weight_shape, output_shape, stride, padding, dilation, groups, bias, core_mask);
|
||
}
|
||
|
||
**私有存储版本:**
|
||
|
||
.. c:function:: void i8_adder_p(int8_t* input_x, int8_t* input_w, int8_t* out_y, int* bias, ConvParameter *conv_param)
|
||
.. c:function:: void hp_adder_p(half* input_x, half* input_w, half* out_y, half* bias, ConvParameter *conv_param)
|
||
.. c:function:: void fp_adder_p(float* input_x, float* input_w, float* out_y, float* bias, ConvParameter *conv_param)
|
||
|
||
**C调用示例:**
|
||
|
||
.. code-block:: c
|
||
:linenos:
|
||
:emphasize-lines: 27
|
||
|
||
void TestAdderL2Fp32(int* input_shape, int* weight_shape, int* output_shape, int* stride, int* padding, int* dilation, int groups, float* bias) {
|
||
float* input_data = (float*)0x10010000;
|
||
float* weight = (float*)0x10020000;
|
||
float* output_data = (float*)0x10030000;
|
||
float* bias_data = (float*)0x10040000;
|
||
ConvParameter* param = (ConvParameter*)0x10060000;
|
||
memcpy(bias_data, bias, sizeof(float) * output_shape[3]);
|
||
param->dilation_h_ = dilation[0];
|
||
param->dilation_w_ = dilation[1];
|
||
param->group_ = groups;
|
||
param->input_batch_ = input_shape[0];
|
||
param->input_h_ = input_shape[1];
|
||
param->input_w_ = input_shape[2];
|
||
param->input_channel_ = input_shape[3];
|
||
param->kernel_h_ = weight_shape[1];
|
||
param->kernel_w_ = weight_shape[2];
|
||
param->output_batch_ = output_shape[0];
|
||
param->output_h_ = output_shape[1];
|
||
param->output_w_ = output_shape[2];
|
||
param->output_channel_ = output_shape[3];
|
||
param->stride_h_ = stride[0];
|
||
param->stride_w_ = stride[0];
|
||
param->pad_u_ = padding[0];
|
||
param->pad_l_ = padding[2];
|
||
param->workspace_ = (float*)0x10070000;
|
||
param->buffer_size_ = 2048;
|
||
fp_adder_p(input_data, weight, output_data, bias_data, param);
|
||
}
|
||
|
||
void main(){
|
||
int in_channel = 4;
|
||
int out_channel = 4;
|
||
int groups = 4;
|
||
int input_shape[4] = {1, 30, 30, in_channel}; // NHWC
|
||
int weight_shape[4] = {out_channel, 3, 3, in_channel / groups};
|
||
int output_shape[4] = {1, 10, 10, out_channel}; // NHWC
|
||
int stride[2] = {2, 2};
|
||
int padding[4] = {1, 1, 1, 1};
|
||
int dilation[2]= {2, 2};
|
||
float bias[4] = {0, 0, 0, 0};
|
||
TestAdderL2Fp32(input_shape, weight_shape, output_shape, stride, padding, dilation, groups, bias);
|
||
}
|