# Subgrad — MindSpore Signal+ 使用手册 alpha 文档

# Subgrad

计算逐元素减法（Sub）操作的梯度。该算子是 Sub 算子的反向传播（backward pass）部分，支持广播。

\[\text{dx1} = \frac{\partial L}{\partial X1} = \frac{\partial L}{\partial Y} \times 1 = \frac{\partial L}{\partial Y}\]
\[\text{dx2} = \frac{\partial L}{\partial X2} = \frac{\partial L}{\partial Y} \times (-1) = -\frac{\partial L}{\partial Y}\]

其中对于前向操作 \(Y = X1 - X2\)，dy 是来自后一层的上游梯度，dx1 和 dx2 分别是对 X1 和 X2 的梯度。

输入：

  - dy - 上游梯度数据地址（即 \(\frac{\partial L}{\partial Y}\)）。

  - x1_dims - 前向传播时第一个输入 x1 的维度信息数组（int*）。

  - x2_dims - 前向传播时第二个输入 x2 的维度信息数组（int*）。

  - dy_dims - 上游梯度 dy 的维度信息数组（int*）。

  - num_dims - 维度数（int）。

  - core_mask - 核掩码（int），仅共享存储版本需要。

输出：

  - dx1 - 对 x1 的梯度数据地址。

  - dx2 - 对 x2 的梯度数据地址。

支持平台：

  `FT78NE` `MT7004`

备注

- MT7004 支持fp16, fp32

- FT78NE 支持fp32

- 当输入张量被广播时，算子会自动处理广播维度的梯度累加

共享存储版本:

void hp_subgrad_s(half *dy, int *x1_dims, int *x2_dims, int *dy_dims, int num_dims, half *dx1, half *dx2, int core_mask)

void fp_subgrad_s(float *dy, int *x1_dims, int *x2_dims, int *dy_dims, int num_dims, float *dx1, float *dx2, int core_mask)

C调用示例：

     1//MT7004示例
     2#include <stdio.h>
     3#include <subgrad.h>
     4
     5int main(int argc, char* argv[]) {
     6    float *dy = (float *)0xA0000000;   // 上游梯度在DDR空间
     7    float *dx1 = (float *)0xB0000000;  // dx1输出
     8    float *dx2 = (float *)0xC0000000;  // dx2输出
     9
    10    // 示例：x1形状 [3, 1]，x2形状 [1, 4]，dy形状 [3, 4]
    11    int x1_dims[] = {3, 1};
    12    int x2_dims[] = {1, 4};
    13    int dy_dims[] = {3, 4};
    14    int num_dims = 2;
    15
    16    int core_mask = 0xff;
    17
    18    fp_subgrad_s(dy, x1_dims, x2_dims, dy_dims, num_dims, dx1, dx2, core_mask);
    19
    20    return 0;
    21}

私有存储版本:

void hp_subgrad_p(half *dy, int *x1_dims, int *x2_dims, int *dy_dims, int num_dims, half *dx1, half *dx2)

void fp_subgrad_p(float *dy, int *x1_dims, int *x2_dims, int *dy_dims, int num_dims, float *dx1, float *dx2)

C调用示例：

     1//MT7004示例
     2#include <stdio.h>
     3#include <subgrad.h>
     4
     5int main(int argc, char* argv[]) {
     6    float *dy = (float *)0x10000000;   // 上游梯度在L2空间
     7    float *dx1 = (float *)0x10001000;  // dx1输出
     8    float *dx2 = (float *)0x10002000;  // dx2输出
     9
    10    int x1_dims[] = {3, 1};
    11    int x2_dims[] = {1, 4};
    12    int dy_dims[] = {3, 4};
    13    int num_dims = 2;
    14
    15    fp_subgrad_p(dy, x1_dims, x2_dims, dy_dims, num_dims, dx1, dx2);
    16
    17    return 0;
    18}