AddGrad
=================


逐元素计算加法梯度

.. math::

    dx1 = \frac{\partial L}{\partial X1} = \frac{\partial L}{\partial Y} * 1 = \frac{\partial L}{\partial Y}\\
    dx2 = \frac{\partial L}{\partial X2} = \frac{\partial L}{\partial Y} * 1 = \frac{\partial L}{\partial Y}

输入：
    - **dy** - dy数据地址。
    - **params** - 参数打包成结构体。
        - **dx1_dim** - x1的维度信息。
        - **dx2_dim** - x2的维度信息。
        - **dy_dims** - dy的维度信息。
        - **num_dims** - 维度数
        - **temp_space** - 临时空间地址，大小为 ``2 * num_dims * 4`` 字节
    - **core_mask** - 核掩码。

输出：
    - **dx1** - dx1的数据地址。
    - **dx2** - dx2的数据地址。

支持平台：
    ``FT78NE``
    ``MT7004``

.. note::
    - FT78NE 支持fp32
    - MT7004 支持fp16, fp32
    - dx1_dim, dx2_dim, dy_dims, num_dims按顺序打包成了一个long long型数组


**共享存储版本:**

.. c:function:: void fp_add_grad_s(float* dy, float* dx1, float* dx2, long long *params, int core_mask)
.. c:function:: void hp_add_grad_s(half* dy, half* dx1, half* dx2, long long *params, int core_mask)

**C调用示例：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 35

    //FT78NE示例
    #include <stdio.h>
    #include <addgrad.h>
    
    int main(int argc, char* argv[]) {
        float *dy = (float *)0x81000000;
        float *dx1 = (float *)0x82000000;
        float *dx2 = (float *)0x83000000;
        int *tempspace = (int *)0x84000000;
        int core_mask = 0b1111;
    
        int i;
        
        // same shape
        int dx1_dims[] = {4, 8, 32};  //1024
        int dx2_dims[] = {1, 8, 32};  //
        int dy_dims[] = {4, 8, 32};  //
        int num_dims = 3;
        
        int dx1_num = get_total_elements(num_dims, dx1_dims);  
        int dx2_num = get_total_elements(num_dims, dx2_dims);
        int dy_num  = get_total_elements(num_dims, dy_dims);

        for (i = 0; i < dy_num; ++i) {
            dy[i] = (float)(rand() % 100) / 10.0f;
        }
        
        long long params[6];
        params[0] = (unsigned long long)dx1_dims;
        params[1] = (unsigned long long)dx2_dims;
        params[2] = (unsigned long long)dy_dims;
        params[3] = (unsigned long long)num_dims;
        params[4] = (unsigned long long)tempspace;

        fp_add_grad_s(dy, dx1, dx2, params, core_mask);        
        return 0;
    }


**私有存储版本:**

.. c:function:: void fp_add_grad_p(float* dy, float* dx1, float* dx2, long long *params)
.. c:function:: void hp_add_grad_p(half* dy, half* dx1, half* dx2, long long *params)


**C调用示例：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 34

    //FT04示例
    #include <stdio.h>
    #include <addgrad.h>
    
    int main(int argc, char* argv[]) {
        float *dy = (float *)0x10010000;
        float *dx1 = (float *)0x10020000;
        float *dx2 = (float *)0x10030000;
        int *tempspace = (int *)0x10040000;
    
        int i;
        
        // same shape
        int dx1_dims[] = {4, 8, 32};  //1024
        int dx2_dims[] = {1, 8, 32};  //
        int dy_dims[] = {4, 8, 32};  //
        int num_dims = 3;
        
        int dx1_num = get_total_elements(num_dims, dx1_dims);  
        int dx2_num = get_total_elements(num_dims, dx2_dims);
        int dy_num  = get_total_elements(num_dims, dy_dims);

        for (i = 0; i < dy_num; ++i) {
            dy[i] = (float)(rand() % 100) / 10.0f;
        }
        
        long long params[6];
        params[0] = (unsigned long long)dx1_dims;
        params[1] = (unsigned long long)dx2_dims;
        params[2] = (unsigned long long)dy_dims;
        params[3] = (unsigned long long)num_dims;
        params[4] = (unsigned long long)tempspace;

        fp_add_grad_p(dy, dx1, dx2, params);        
        return 0;
    }