265 lines
10 KiB
ReStructuredText
265 lines
10 KiB
ReStructuredText
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, ¶ms, 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, ¶ms);
|
||
}
|
||
|
||
|