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

# GLU

Gated Linear Unit（门控线性单元）算子。该算子将输入张量在指定维度（`split_dim`）上分割成两个相等的部分（A和B），然后对第二部分（B）应用Sigmoid激活函数，并将其与第一部分（A）逐元素相乘。

\[\text{out} = A \otimes \sigma(B)\]

其中，A和B是输入张量沿 `split_dim` 维度分割后的两个子张量，\(\sigma\) 是Sigmoid函数，\(\otimes\) 表示逐元素乘法。

输入：

  - in_data - 输入张量的数据地址。

  - split_data - 一个指针数组，用于存放分割后的子张量地址（作为临时缓冲区）。

  - out_data - 输出张量的数据地址。

  - ndim - 输入张量的维度数量。

  - split_dim - 执行分割操作的目标维度轴。

  - input_shape - 指向一个整数数组的指针，该数组描述了输入张量的形状。

  - num_split - 分割的数量，对于GLU操作，此值应为2。

  - split_sizes - 指向一个整数数组的指针，该数组描述了每个子张量在 `split_dim` 维度上的大小。

  - strides - 指向一个整数数组的指针，用于存放为张量索引预先计算好的步长。

  - len - 输出张量中的元素总数。

  - core_mask - 核掩码 (仅共享存储版本需要)。

输出：

  - out_data - 存储GLU计算结果的张量。其形状与输入张量相同，但在 `split_dim` 维度上的大小减半。

支持平台：

  `FT78NE` `MT7004`

备注

- FT78NE支持fp32和int8类型。

- MT7004支持fp16和fp32类型。

共享存储版本:

void i8_glu_s(int8_t *in_data, int8_t **split_data, int8_t *out_data, int ndim, int split_dim, int *input_shape, int num_split, int *split_sizes, int *strides, int len, int core_mask)

void hp_glu_s(half *in_data, half **split_data, half *out_data, int ndim, int split_dim, int *input_shape, int num_split, int *split_sizes, int *strides, int len, int core_mask)

void fp_glu_s(float *in_data, float **split_data, float *out_data, int ndim, int split_dim, int *input_shape, int num_split, int *split_sizes, int *strides, int len, int core_mask)

C调用示例：

     1// 7004平台, fp32示例
     2#include <stdio.h>
     3#include "glu.h"
     4
     5int main(int argc, char* argv[]) {
     6    float *in_data = (float *)0xA0000000;      // input在DDR空间
     7    float *out_data = (float *)0xC0000000;     // output在DDR空间
     8    float *split_data_buf[2];                  // 临时缓冲区指针
     9    // ... (需要为split_data_buf分配内存)
    10
    11    // 假设张量属性已定义
    12    int ndim = 2;
    13    int split_dim = 1;
    14    int input_shape[] = {2, 4};
    15    int num_split = 2;
    16    int split_sizes[] = {2, 2};
    17    int len = 4;
    18    int strides[2]; // 需要预先计算
    19    int core_mask = 0xff;
    20
    21    fp_glu_s(in_data, split_data_buf, out_data, ndim, split_dim, input_shape, num_split, split_sizes, strides, len, core_mask);
    22    return 0;
    23}

私有存储版本:

void i8_glu_p(int8_t *in_data, int8_t **split_data, int8_t *out_data, int ndim, int split_dim, int *input_shape, int num_split, int *split_sizes, int *strides, int len)

void hp_glu_p(half *in_data, half **split_data, half *out_data, int ndim, int split_dim, int *input_shape, int num_split, int *split_sizes, int *strides, int len)

void fp_glu_p(float *in_data, float **split_data, float *out_data, int ndim, int split_dim, int *input_shape, int num_split, int *split_sizes, int *strides, int len)

C调用示例：

     1// 7004平台, fp32示例
     2#include <stdio.h>
     3#include "glu.h"
     4
     5int main(int argc, char* argv[]) {
     6    float *in_data = (float *)0x10000000;     // input在L2空间
     7    float *out_data = (float *)0x10001000;    // output在L2空间
     8    float *split_data_buf[2];                 // 临时缓冲区指针
     9    // ... (需要为split_data_buf分配内存)
    10
    11    // 假设张量属性已定义
    12    int ndim = 2;
    13    int split_dim = 1;
    14    int input_shape[] = {2, 4};
    15    int num_split = 2;
    16    int split_sizes[] = {2, 2};
    17    int len = 4;
    18    int strides[2]; // 需要预先计算
    19
    20    fp_glu_p(in_data, split_data_buf, out_data, ndim, split_dim, input_shape, num_split, split_sizes, strides, len);
    21    return 0;
    22}