FT_DSP.gitlink.net/master/html/_sources/functionlib/dsplib/adder.rst.txt

170 lines
7.0 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

AdderFusion
=================
Adder是一种卷积替代算子它使用L1距离度量绝对差的和代替传统卷积中的点积操作。与标准卷积不同Adder通过计算特征与卷积核之间的绝对差的负和来进行特征提取。假定输入Xfilter表示为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);
}