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

265 lines
10 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.

Divgrad
=================
计算逐元素除法操作 (`Y = x1 / x2`) 的梯度。
.. math::
dx_1 = \frac{\partial L}{\partial x_1} = \frac{\partial L}{\partial Y} \cdot \frac{1}{x_2} = \frac{dy}{x_2}
.. math::
dx_2 = \frac{\partial L}{\partial x_2} = \frac{\partial L}{\partial Y} \cdot \frac{-x_1}{x_2^2} = - \frac{dy \cdot x_1}{x_2^2}
Divgrad1l版本专门用于 `x1` 张量维度大于或等于 `x2` 张量的广播场景。Divgrad2l版本专门用于 `x2` 张量维度大于或等于 `x1` 张量的广播场景。
输入:
- **dy** - 来自后一层的上游梯度张量。
- **x1** - 前向传播时的第一个输入张量(被除数)。
- **x2** - 前向传播时的第二个输入张量(除数)。
- **params** - 参数打包成结构体。
- **large_shape** - `x1``x2` 中维度较大的张量的形状。
- **small_shape** - `x1``x2` 中维度较小的张量的形状。
- **out_shape** - 输出张量 `dx1``dx2` 的形状。
- **ndims** - 张量的维度数。
- **large_strides** - 维度较大张量的步长信息。
- **small_strides** - 维度较小张量的步长信息。
- **out_strides** - 输出张量的步长信息。
- **large_multiples** - 维度较大张量的广播倍数。
- **small_multiples** - 维度较小张量的广播倍数。
- **tile_data0** - 临时工作空间地址。
- **tile_data1** - 临时工作空间地址。
- **tile_data2** - 临时工作空间地址。
- **indices** - 用于广播计算的临时索引空间地址。
- **core_mask** - 核掩码。
输出:
- **dx1** - 写入计算出的对 `x1` 的梯度。
- **dx2** - 写入计算出的对 `x2` 的梯度。
支持平台:
``FT78NE``
``MT7004``
.. note::
- FT78NE 支持fp32
- MT7004 支持fp16, fp32
**参数结构体:**
.. code-block:: c
:linenos:
typedef struct {
void *tile_data0; //中间结果,不需要初始化, 0
void *tile_data1; //中间结果,不需要初始化, 1
void *tile_data2; //中间结果,不需要初始化, 2
int *large_shape; //输入需要初始化维度是ndims表示x1和x2中比较大的维度, 3
int *small_shape; //输入需要初始化维度是ndims表示x1和x2中比较小的维度, 4
int *out_shape; //输出需要初始化维度是ndims, 5
long long ndims; //维度数,需要初始化, 6
long long dy_size; //dy元素个数需要初始化, 7
long long x1_size; //x1元素个数需要初始化, 8
long long x2_size; //x2元素个数需要初始化, 9
int *large_strides; //x1的strides需要初始化维度是ndims, 10
int *small_strides; //x2的strides需要初始化维度是ndims, 11
int *out_strides; //out的strides需要初始化维度是ndims, 12
int *large_multiples; //x1的multiples需要初始化维度是ndims, 13
int *small_multiples; //x2的multiples需要初始化维度是ndims, 14
int *indices; //临时空间维度为ndims,必须初始化为0; 下标15
int *x1_shape; //x1的维度, 16
int *x2_shape; //x2的维度, 17
} Parameter;
**共享存储版本:**
.. c:function:: void fp_div_grad_s(float *dy, float *dx1, float *dx2, float *x1_data, float *x2_data, Parameter *params, int core_mask);
.. c:function:: void hp_div_grad_s(float16 *dy, float16 *dx1, float16 *dx2, float16 *x1_data, float16 *x2_data, Parameter *params, int core_mask);
**C调用示例**
.. code-block:: c
:linenos:
:emphasize-lines: 39
//FT78NE示例
#include <stdio.h>
#include <divgrad.h>
int main(int argc, char* argv[]) {
float *dy = (float *)0x81000000;//输入,初始化
float *dx1 = (float *)0x82000000;//输出,需要初始化
float *dx2 = (float *)0x83000000;//输出,需要初始化
float *x1_data = (float *)0x84000000;//输入,需要初始化
float *x2_data = (float *)0x85000000;//输入,需要初始化
float *tile_data0 = (float *)0x86000000;//中间结果,不需要初始化
float *tile_data1 = (float *)0x87000000;//中间结果,不需要初始化
float *tile_data2 = (float *)0x88000000;//中间结果,不需要初始化
float *check_dx1 = (float *)0x89000000;//输出,需要初始化
float *check_dx2 = (float *)0x8A000000;//输出,需要初始化
long long ndims = 4;
long long dy_size;
long long x1_size;
long long x2_size;
int *large_strides = (int *)0x8B000000;//不需要初始化
int *small_strides = (int *)0x8B100000; //不需要初始化
int *out_strides = (int *)0x8B200000; //不需要初始化
int *large_multiples = (int *)0x8B300000; //不需要初始化
int *small_multiples = (int *)0x8B400000; //不需要初始化
int *indices = (int *)0x8B500000;
int *x1_shape = (int *)0x8B600000;
int *x2_shape = (int *)0x8B700000;
int i = 0;
srand(seed++);
//初始化
x1_shape[0] = 4; x1_shape[1] = 4; x1_shape[2] = 4; x1_shape[3] = 4;
x2_shape[0] = 4; x2_shape[1] = 4; x2_shape[2] = 4; x2_shape[3] = 1;
int *large_shape = x1_shape;
int *small_shape = x2_shape;
int *output_shape = large_shape;
dy_size = output_shape[0] * output_shape[1] * output_shape[2] * output_shape[3];
x1_size = x1_shape[0] * x1_shape[1] * x1_shape[2] * x1_shape[3];
x2_size = x2_shape[0] * x2_shape[1] * x2_shape[2] * x2_shape[3];
for(i = 0; i < dy_size; ++i) {
dy[i] = (float)(rand()%1000)/100 + 1.0f;
}
for(i = 0; i < x1_size; ++i) {
x1_data[i] = (float)(rand()%1000)/100 + 1.0f;
}
for(i = 0; i < x2_size; ++i) {
x2_data[i] = (float)(rand()%1000)/100 + 1.0f;
}
memset(indices, 0, ndims*sizeof(int));
Parameter params;
params.tile_data0 = tile_data0; //5
params.tile_data1 = tile_data1; //6
params.tile_data2 = tile_data2; //7
params.large_shape = large_shape;
params.small_shape = small_shape;
params.out_shape = output_shape;
params.ndims = ndims;
params.dy_size = dy_size;
params.x1_size = x1_size;
params.x2_size = x2_size;
params.large_strides = large_strides;
params.small_strides = small_strides;
params.out_strides = out_strides;
params.large_multiples = large_multiples;
params.small_multiples = small_multiples;
params.indices = indices;
params.x1_shape = x1_shape;
params.x2_shape = x2_shape;
fp_div_grad_s(dy, dx1, dx2, x1_data, x2_data, &params, core_mask);
}
**私有存储版本:**
.. c:function:: void fp_div_grad_p(float *dy, float *dx1, float *dx2, float *x1_data, float *x2_data, Parameter *params);
.. c:function:: void hp_div_grad_p(float16 *dy, float16 *dx1, float16 *dx2, float16 *x1_data, float16 *x2_data, Parameter *params);
**C调用示例**
.. code-block:: c
:linenos:
:emphasize-lines: 37
//FT78NE示例
#include <stdio.h>
#include <divgrad.h>
int main(int argc, char* argv[]) {
float *dy = (float *)0x10010000;//输入,初始化
float *dx1 = (float *)0x10016000;//输出,需要初始化
float *dx2 = (float *)0x10020000;//输出,需要初始化
float *x1_data = (float *)0x10026000;//输入,需要初始化
float *x2_data = (float *)0x10030000;//输入,需要初始化
float *tile_data0 = (float *)0x10036000;//中间结果,不需要初始化
float *tile_data1 = (float *)0x10040000;//中间结果,不需要初始化
float *tile_data2 = (float *)0x10046000;//中间结果,不需要初始化
int *x1_shape = (int *)0x10050000;
int *x2_shape = (int *)0x10051000;
long long ndims = 4;
long long dy_size;
long long x1_size;
long long x2_size;
int *large_strides = (int *)0x10053000;//不需要初始化
int *small_strides = (int *)0x10054000; //不需要初始化
int *out_strides = (int *)0x10055000; //不需要初始化
int *large_multiples = (int *)0x10056000; //不需要初始化
int *small_multiples = (int *)0x10057000; //不需要初始化
int *indices = (int *)0x10058000;
int i = 0;
srand(seed++);
//初始化
x1_shape[0] = 4; x1_shape[1] = 4; x1_shape[2] = 4; x1_shape[3] = 4;
x2_shape[0] = 4; x2_shape[1] = 4; x2_shape[2] = 4; x2_shape[3] = 1;
int *large_shape = x1_shape;
int *small_shape = x2_shape;
int *output_shape = large_shape;
dy_size = output_shape[0] * output_shape[1] * output_shape[2] * output_shape[3];
x1_size = x1_shape[0] * x1_shape[1] * x1_shape[2] * x1_shape[3];
x2_size = x2_shape[0] * x2_shape[1] * x2_shape[2] * x2_shape[3];
for(i = 0; i < dy_size; ++i) {
dy[i] = (float)(rand()%1000)/100 + 1.0f;
}
for(i = 0; i < x1_size; ++i) {
x1_data[i] = (float)(rand()%1000)/100 + 1.0f;
}
for(i = 0; i < x2_size; ++i) {
x2_data[i] = (float)(rand()%1000)/100 + 1.0f;
}
memset(indices, 0, ndims*sizeof(int));
Parameter params;
params.tile_data0 = tile_data0; //5
params.tile_data1 = tile_data1; //6
params.tile_data2 = tile_data2; //7
params.large_shape = large_shape;
params.small_shape = small_shape;
params.out_shape = output_shape;
params.ndims = ndims;
params.dy_size = dy_size;
params.x1_size = x1_size;
params.x2_size = x2_size;
params.large_strides = large_strides;
params.small_strides = small_strides;
params.out_strides = out_strides;
params.large_multiples = large_multiples;
params.small_multiples = small_multiples;
params.indices = indices;
params.x1_shape = x1_shape;
params.x2_shape = x2_shape;
fp_div_grad_p(dy, dx1, dx2, x1_data, x2_data, &params);
}