Merged
fix(mhc): 新增 TextGatedResidualGrad 和Readme文档 #15537
azyuliAdd on 6 days ago
fix(mhc): 新增 TextGatedResidualGrad 和Readme文档 #15537
Merged
Total: 3 files changed+671-0
| @@ -0,0 +1,145 @@ | |||
| 1 | +# TextGatedResidualGrad | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +| 产品 | 是否支持 | | ||
| 6 | +| :--- | :---: | | ||
| 7 | +| <term>Ascend 950PR&950DT系列产品</term> | √ | | ||
| 8 | +| <term>Atlas A3系列产品</term> | √ | | ||
| 9 | +| <term>Atlas A2系列产品</term> | √ | | ||
| 10 | +| <term>Atlas 200I/500 A2推理产品</term> | × | | ||
| 11 | +| <term>Atlas推理系列产品</term> | × | | ||
| 12 | +| <term>Atlas训练系列产品</term> | × | | ||
| 13 | + | ||
| 14 | +## 功能说明 | ||
| 15 | + | ||
| 16 | +`TextGatedResidualGrad` 是 `TextGatedResidual` 的反向算子。根据混合输出和注入输出的上游梯度,以及前向保存的张量,计算输入 `x` 和权重 `wDown`、`wUp`、`wGate`、`gamma` 的梯度。 | ||
| 17 | + | ||
| 18 | +记 $B$ 为批大小,$S$ 为序列长度,$C$ 为通道数,$H$ 为每通道的特征数,$R$ 为下投影维度,$D=C\times H$。$\odot$ 表示逐元素乘法,$@$ 表示矩阵乘法,$\sigma$ 表示 Sigmoid 函数。 | ||
| 19 | + | ||
| 20 | +对应的前向计算为: | ||
| 21 | + | ||
| 22 | +$$ | ||
| 23 | +\begin{aligned} | ||
| 24 | +\mathrm{invRms}_{b,s,c} &= \left(\frac{1}{H}\sum_{j=0}^{H-1}x_{b,s,c,j}^{2}+\epsilon\right)^{-1/2} \\ | ||
| 25 | +\mathrm{xNorm} &= x\odot\mathrm{invRms}\odot(1+\gamma) \\ | ||
| 26 | +\mathrm{downPreAct} &= \mathrm{xNorm}@\mathrm{wDown}^{T} \\ | ||
| 27 | +\mathrm{act} &= \mathrm{SiLU}(\mathrm{downPreAct}/C) \\ | ||
| 28 | +\mathrm{up} &= \mathrm{act}@\mathrm{wUp}^{T} \\ | ||
| 29 | +\mathrm{mixed}_{b,s,j} &= \frac{1}{C}\sum_{c=0}^{C-1}\mathrm{xNorm}_{b,s,c,j}\,\sigma(\mathrm{up}_{b,s,c,j}) \\ | ||
| 30 | +\mathrm{inject} &= 2\sigma\!\left((\mathrm{xNorm}@\mathrm{wGate}^{T})/C\right) | ||
| 31 | +\end{aligned} | ||
| 32 | +$$ | ||
| 33 | + | ||
| 34 | +其中,归一化及通道求和时将最后一维 $D$ 视为 $[C,H]$,矩阵乘法时仍使用最后一维 $D$。`invRms` 在每个通道的 $H$ 个特征上广播,`gamma` 在 $B$、$S$ 维上广播。$\epsilon$ 是前向归一化使用的参数,本接口通过 `invRms` 接收对应的前向结果。 | ||
| 35 | + | ||
| 36 | +给定 `gradMixed` 和 `gradInject`,定义 | ||
| 37 | + | ||
| 38 | +$$ | ||
| 39 | +L=\sum_{b,s,j}\mathrm{gradMixed}_{b,s,j}\,\mathrm{mixed}_{b,s,j} | ||
| 40 | + +\sum_{b,s,c}\mathrm{gradInject}_{b,s,c}\,\mathrm{inject}_{b,s,c}. | ||
| 41 | +$$ | ||
| 42 | + | ||
| 43 | +本算子的输出为: | ||
| 44 | + | ||
| 45 | +$$ | ||
| 46 | +dx=\frac{\partial L}{\partial x},\quad | ||
| 47 | +dwDown=\frac{\partial L}{\partial wDown},\quad | ||
| 48 | +dwUp=\frac{\partial L}{\partial wUp},\quad | ||
| 49 | +dwGate=\frac{\partial L}{\partial wGate},\quad | ||
| 50 | +dgamma=\frac{\partial L}{\partial\gamma}. | ||
| 51 | +$$ | ||
| 52 | + | ||
| 53 | +`wGate` 缺省时不包含注入分支及其梯度;`gamma` 缺省时归一化缩放系数为 1,不输出 `dgamma`。`invRms`、`inject`、`downPreAct`、`up` 必须来自同一次前向计算,并与本次传入的输入、权重对应。 | ||
| 54 | + | ||
| 55 | +## 参数说明 | ||
| 56 | + | ||
| 57 | +| 参数名 | 输入/输出/属性 | 描述 | 数据类型 | 数据格式 | shape | | ||
| 58 | +| :--- | :--- | :--- | :--- | :--- | :--- | | ||
| 59 | +| gradMixed | 输入 | 混合输出 mixed 的上游梯度。 | FLOAT16、BFLOAT16 | ND | [B,S,H] | | ||
| 60 | +| x | 输入 | 前向输入。 | FLOAT16、BFLOAT16 | ND | [B,S,D] | | ||
| 61 | +| wDown | 输入 | 下投影权重。 | FLOAT16、BFLOAT16 | ND | [R,D] | | ||
| 62 | +| wUp | 输入 | 上投影权重。 | FLOAT16、BFLOAT16 | ND | [D,R] | | ||
| 63 | +| invRms | 输入 | 前向保存的各通道均方根倒数。 | FLOAT32 | ND | [B,S,C] | | ||
| 64 | +| downPreAct | 输入 | 前向保存的下投影结果 xNorm@wDownᵀ。 | FLOAT16、BFLOAT16 | ND | [B,S,R] | | ||
| 65 | +| up | 输入 | 前向保存的上投影结果 act@wUpᵀ。 | FLOAT16、BFLOAT16 | ND | [B,S,D] | | ||
| 66 | +| gradInject | 可选输入 | 注入输出 inject 的上游梯度。 | FLOAT16、BFLOAT16 | ND | [B,S,C] | | ||
| 67 | +| wGate | 可选输入 | 注入分支权重。 | FLOAT16、BFLOAT16 | ND | [C,D] | | ||
| 68 | +| gamma | 可选输入 | 归一化缩放权重,实际缩放系数为 1+gamma。 | FLOAT32 | ND | [D] | | ||
| 69 | +| inject | 可选输入 | 前向保存的注入输出 2*sigmoid((xNorm@wGateᵀ)/C)。 | FLOAT16、BFLOAT16 | ND | [B,S,C] | | ||
| 70 | +| channels | 属性 | 通道数 C。 | INT64 | - | 标量 | | ||
| 71 | +| dx | 输出 | x 的梯度。 | 同 x | ND | [B,S,D] | | ||
| 72 | +| dwDown | 输出 | wDown 的梯度。 | FLOAT16、BFLOAT16 | ND | [R,D] | | ||
| 73 | +| dwUp | 输出 | wUp 的梯度。 | FLOAT16、BFLOAT16 | ND | [D,R] | | ||
| 74 | +| dwGate | 可选输出 | wGate 的梯度。 | FLOAT16、BFLOAT16 | ND | [C,D] | | ||
| 75 | +| dgamma | 可选输出 | gamma 的梯度。 | FLOAT32 | ND | [D] | | ||
| 76 | + | ||
| 77 | +## 约束说明 | ||
| 78 | + | ||
| 79 | +- `C`、`H`、`R` 为正整数;`H`、`R` 均须为 16 的整数倍。 | ||
| 80 | + | ||
| 81 | +通道数须满足 `C ≤ 20`。 | ||
| 82 | + | ||
| 83 | +`H` 的取值范围按产品确定。令 | ||
| 84 | + | ||
| 85 | +<!-- npu="950" id7 --> | ||
| 86 | +- <term>Ascend 950PR&950DT系列产品</term>: | ||
| 87 | + | ||
| 88 | + $$ | ||
| 89 | + K = 62448-16\left\lceil C/8\right\rceil | ||
| 90 | + $$ | ||
| 91 | + | ||
| 92 | +<!-- end id7 --> | ||
| 93 | +<!-- npu="A3,910b" id8 --> | ||
| 94 | +- <term>Atlas A2系列产品</term>、<term>Atlas A3系列产品</term>: | ||
| 95 | + | ||
| 96 | + $$ | ||
| 97 | + K = 39664-16\left\lceil C/8\right\rceil | ||
| 98 | + $$ | ||
| 99 | + | ||
| 100 | +<!-- end id8 --> | ||
| 101 | + | ||
| 102 | +`H`、`R` 须同时满足: | ||
| 103 | + | ||
| 104 | +$$ | ||
| 105 | +\boxed{ | ||
| 106 | +\begin{aligned} | ||
| 107 | +13H &\le K,\\ | ||
| 108 | +3H+8R &\le K,\\ | ||
| 109 | +7H+6R &\le K. | ||
| 110 | +\end{aligned} | ||
| 111 | +} | ||
| 112 | +$$ | ||
| 113 | + | ||
| 114 | +因此,给定 `C` 后,`H` 的上限为 | ||
| 115 | + | ||
| 116 | +$$ | ||
| 117 | +H_{\max}=16\left\lfloor\frac{K}{208}\right\rfloor. | ||
| 118 | +$$ | ||
| 119 | + | ||
| 120 | +`R` 须同时满足上述关系式和 `R ≤ 640`。 | ||
| 121 | + | ||
| 122 | +其中,$\lceil\cdot\rceil$ 表示向上取整,$\lfloor\cdot\rfloor$ 表示向下取整。上述关系适用于 FLOAT16、BFLOAT16,以及所有合法的可选参数组合。 | ||
| 123 | + | ||
| 124 | +例如,`C=4、H=2560、R=320` 适用于上述三类产品。其他 `C/H/R` 组合须满足上述约束。调用时仍需通过第一段接口 `aclnnTextGatedResidualGradGetWorkspaceSize` 完成参数校验,并按返回的 `workspaceSize` 申请内存。 | ||
| 125 | + | ||
| 126 | +- 所有 FLOAT16/BFLOAT16 输入以及 `dx`、`dwDown`、`dwUp`、`dwGate` 的数据类型必须一致;各权重梯度与对应权重的数据类型相同。`invRms`、`gamma` 和 `dgamma` 为 FLOAT32。 | ||
| 127 | +- 支持非连续输入 Tensor。输入输出的 shape 必须符合参数表,同名维度的大小必须一致。 | ||
| 128 | +- 支持 `B=0` 或 `S=0`:`dx` 为空,已提供的非空权重梯度和 `dgamma` 全部置零,其余参数仍须满足上述约束。 | ||
| 129 | +- 输出梯度覆盖写入,调用前无需初始化,也不会累加到输出 Tensor 的原有数据中。 | ||
| 130 | +- 默认执行确定性计算。 | ||
| 131 | + | ||
| 132 | +ACLNN 调用时,可选参数须满足以下要求: | ||
| 133 | + | ||
| 134 | +| 功能 | 提供时 | 缺省时 | | ||
| 135 | +| :--- | :--- | :--- | | ||
| 136 | +| 注入分支 | `wGate`、`gradInject`、`inject`、`dwGate` 四者必须同时提供 | 四者必须全部传入 `nullptr` | | ||
| 137 | +| 归一化缩放 | `gamma`、`dgamma` 必须同时提供 | 两者必须全部传入 `nullptr`,缩放系数取 1 | | ||
| 138 | + | ||
| 139 | +两组可选参数相互独立。`nullptr` 表示省略该功能,不能用 shape 为 `[0]` 的占位 Tensor 代替。 | ||
| 140 | + | ||
| 141 | +## 调用说明 | ||
| 142 | + | ||
| 143 | +| 调用方式 | 调用样例 | 说明 | | ||
| 144 | +| :--- | :--- | :--- | | ||
| 145 | +| aclnn 调用 | [接口调用示例](./docs/aclnnTextGatedResidualGrad.md#调用示例) | 创建输入输出 Tensor,调用两段式接口获取并执行计算。 | | ||
| @@ -0,0 +1,145 @@ | |||
| 1 | +# TextGatedResidualGrad | ||
| 2 | + | ||
| 3 | +## Supported Products | ||
| 4 | + | ||
| 5 | +| Product | Supported | | ||
| 6 | +| :--- | :---: | | ||
| 7 | +| <term>Ascend 950PR & 950DT Series</term> | √ | | ||
| 8 | +| <term>Atlas A3 Series</term> | √ | | ||
| 9 | +| <term>Atlas A2 Series</term> | √ | | ||
| 10 | +| <term>Atlas 200I/500 A2 Inference Products</term> | × | | ||
| 11 | +| <term>Atlas Inference Series</term> | × | | ||
| 12 | +| <term>Atlas Training Series</term> | × | | ||
| 13 | + | ||
| 14 | +## Function | ||
| 15 | + | ||
| 16 | +`TextGatedResidualGrad` is the backward operator of `TextGatedResidual`. It computes gradients of input `x` and weights `wDown`, `wUp`, `wGate`, and `gamma` from the upstream gradients of the mixed and injection outputs and tensors saved during the forward pass. | ||
| 17 | + | ||
| 18 | +Let $B$ denote the batch size, $S$ the sequence length, $C$ the number of channels, $H$ the number of features per channel, $R$ the down-projection dimension, and $D=C\times H$. $\odot$ denotes element-wise multiplication, $@$ denotes matrix multiplication, and $\sigma$ denotes the sigmoid function. | ||
| 19 | + | ||
| 20 | +The corresponding forward computation is: | ||
| 21 | + | ||
| 22 | +$$ | ||
| 23 | +\begin{aligned} | ||
| 24 | +\mathrm{invRms}_{b,s,c} &= \left(\frac{1}{H}\sum_{j=0}^{H-1}x_{b,s,c,j}^{2}+\epsilon\right)^{-1/2} \\ | ||
| 25 | +\mathrm{xNorm} &= x\odot\mathrm{invRms}\odot(1+\gamma) \\ | ||
| 26 | +\mathrm{downPreAct} &= \mathrm{xNorm}@\mathrm{wDown}^{T} \\ | ||
| 27 | +\mathrm{act} &= \mathrm{SiLU}(\mathrm{downPreAct}/C) \\ | ||
| 28 | +\mathrm{up} &= \mathrm{act}@\mathrm{wUp}^{T} \\ | ||
| 29 | +\mathrm{mixed}_{b,s,j} &= \frac{1}{C}\sum_{c=0}^{C-1}\mathrm{xNorm}_{b,s,c,j}\,\sigma(\mathrm{up}_{b,s,c,j}) \\ | ||
| 30 | +\mathrm{inject} &= 2\sigma\!\left((\mathrm{xNorm}@\mathrm{wGate}^{T})/C\right) | ||
| 31 | +\end{aligned} | ||
| 32 | +$$ | ||
| 33 | + | ||
| 34 | +The last dimension $D$ is interpreted as $[C,H]$ for normalization and summation across channels, and remains $D$ for matrix multiplication. `invRms` is broadcast across the $H$ features of each channel; `gamma` is broadcast across the $B$ and $S$ dimensions. $\epsilon$ is the parameter used for forward normalization. This interface receives the corresponding forward result through `invRms`. | ||
| 35 | + | ||
| 36 | +Given `gradMixed` and `gradInject`, define | ||
| 37 | + | ||
| 38 | +$$ | ||
| 39 | +L=\sum_{b,s,j}\mathrm{gradMixed}_{b,s,j}\,\mathrm{mixed}_{b,s,j} | ||
| 40 | + +\sum_{b,s,c}\mathrm{gradInject}_{b,s,c}\,\mathrm{inject}_{b,s,c}. | ||
| 41 | +$$ | ||
| 42 | + | ||
| 43 | +The outputs of this operator are: | ||
| 44 | + | ||
| 45 | +$$ | ||
| 46 | +dx=\frac{\partial L}{\partial x},\quad | ||
| 47 | +dwDown=\frac{\partial L}{\partial wDown},\quad | ||
| 48 | +dwUp=\frac{\partial L}{\partial wUp},\quad | ||
| 49 | +dwGate=\frac{\partial L}{\partial wGate},\quad | ||
| 50 | +dgamma=\frac{\partial L}{\partial\gamma}. | ||
| 51 | +$$ | ||
| 52 | + | ||
| 53 | +When `wGate` is omitted, the injection branch and its gradients are excluded. When `gamma` is omitted, the normalization scale is 1 and `dgamma` is not produced. `invRms`, `inject`, `downPreAct`, and `up` must come from the same forward pass and correspond to the supplied input and weights. | ||
| 54 | + | ||
| 55 | +## Parameters | ||
| 56 | + | ||
| 57 | +| Name | Input/Output/Attribute | Description | Data Type | Format | Shape | | ||
| 58 | +| :--- | :--- | :--- | :--- | :--- | :--- | | ||
| 59 | +| gradMixed | Input | Upstream gradient of the mixed output mixed. | FLOAT16, BFLOAT16 | ND | [B,S,H] | | ||
| 60 | +| x | Input | Forward input. | FLOAT16, BFLOAT16 | ND | [B,S,D] | | ||
| 61 | +| wDown | Input | Down-projection weight. | FLOAT16, BFLOAT16 | ND | [R,D] | | ||
| 62 | +| wUp | Input | Up-projection weight. | FLOAT16, BFLOAT16 | ND | [D,R] | | ||
| 63 | +| invRms | Input | Per-channel reciprocal root mean square saved during the forward pass. | FLOAT32 | ND | [B,S,C] | | ||
| 64 | +| downPreAct | Input | Down-projection result xNorm@wDownᵀ saved during the forward pass. | FLOAT16, BFLOAT16 | ND | [B,S,R] | | ||
| 65 | +| up | Input | Up-projection result act@wUpᵀ saved during the forward pass. | FLOAT16, BFLOAT16 | ND | [B,S,D] | | ||
| 66 | +| gradInject | Optional input | Upstream gradient of the injection output inject. | FLOAT16, BFLOAT16 | ND | [B,S,C] | | ||
| 67 | +| wGate | Optional input | Injection branch weight. | FLOAT16, BFLOAT16 | ND | [C,D] | | ||
| 68 | +| gamma | Optional input | Normalization scale weight; the actual scale is 1+gamma. | FLOAT32 | ND | [D] | | ||
| 69 | +| inject | Optional input | Injection output 2*sigmoid((xNorm@wGateᵀ)/C) saved during the forward pass. | FLOAT16, BFLOAT16 | ND | [B,S,C] | | ||
| 70 | +| channels | Attribute | Number of channels C. | INT64 | - | Scalar | | ||
| 71 | +| dx | Output | Gradient of x. | Same as x | ND | [B,S,D] | | ||
| 72 | +| dwDown | Output | Gradient of wDown. | FLOAT16, BFLOAT16 | ND | [R,D] | | ||
| 73 | +| dwUp | Output | Gradient of wUp. | FLOAT16, BFLOAT16 | ND | [D,R] | | ||
| 74 | +| dwGate | Optional output | Gradient of wGate. | FLOAT16, BFLOAT16 | ND | [C,D] | | ||
| 75 | +| dgamma | Optional output | Gradient of gamma. | FLOAT32 | ND | [D] | | ||
| 76 | + | ||
| 77 | +## Constraints | ||
| 78 | + | ||
| 79 | +- `C`, `H`, and `R` must be positive integers; both `H` and `R` must be multiples of 16. | ||
| 80 | + | ||
| 81 | +The number of channels must satisfy `C ≤ 20`. | ||
| 82 | + | ||
| 83 | +The range of `H` depends on the product. Define | ||
| 84 | + | ||
| 85 | +<!-- npu="950" id7 --> | ||
| 86 | +- <term>Ascend 950PR & 950DT Series</term>: | ||
| 87 | + | ||
| 88 | + $$ | ||
| 89 | + K = 62448-16\left\lceil C/8\right\rceil | ||
| 90 | + $$ | ||
| 91 | + | ||
| 92 | +<!-- end id7 --> | ||
| 93 | +<!-- npu="A3,910b" id8 --> | ||
| 94 | +- <term>Atlas A2 Series</term>, <term>Atlas A3 Series</term>: | ||
| 95 | + | ||
| 96 | + $$ | ||
| 97 | + K = 39664-16\left\lceil C/8\right\rceil | ||
| 98 | + $$ | ||
| 99 | + | ||
| 100 | +<!-- end id8 --> | ||
| 101 | + | ||
| 102 | +`H` and `R` must satisfy all of the following: | ||
| 103 | + | ||
| 104 | +$$ | ||
| 105 | +\boxed{ | ||
| 106 | +\begin{aligned} | ||
| 107 | +13H &\le K,\\ | ||
| 108 | +3H+8R &\le K,\\ | ||
| 109 | +7H+6R &\le K. | ||
| 110 | +\end{aligned} | ||
| 111 | +} | ||
| 112 | +$$ | ||
| 113 | + | ||
| 114 | +Therefore, for a given `C`, the upper bound of `H` is | ||
| 115 | + | ||
| 116 | +$$ | ||
| 117 | +H_{\max}=16\left\lfloor\frac{K}{208}\right\rfloor. | ||
| 118 | +$$ | ||
| 119 | + | ||
| 120 | +`R` must satisfy both the inequalities above and `R ≤ 640`. | ||
| 121 | + | ||
| 122 | +Here, $\lceil\cdot\rceil$ denotes rounding up and $\lfloor\cdot\rfloor$ denotes rounding down. These relationships apply to FLOAT16, BFLOAT16, and all valid combinations of optional parameters. | ||
| 123 | + | ||
| 124 | +For example, `C=4, H=2560, R=320` is valid for all three supported product series. Other `C/H/R` combinations must satisfy the constraints above. Call the first-stage interface `aclnnTextGatedResidualGradGetWorkspaceSize` to validate parameters and allocate memory according to the returned `workspaceSize`. | ||
| 125 | + | ||
| 126 | +- All FLOAT16/BFLOAT16 inputs and `dx`, `dwDown`, `dwUp`, and `dwGate` must have the same data type. Each weight gradient must have the same data type as its corresponding weight. `invRms`, `gamma`, and `dgamma` are FLOAT32. | ||
| 127 | +- Non-contiguous input tensors are supported. Input and output shapes must match the parameter table, and dimensions with the same name must have the same size. | ||
| 128 | +- `B=0` or `S=0` is supported: `dx` is empty, and all supplied non-empty weight gradients and `dgamma` are set to zero. Other parameters must still satisfy the constraints above. | ||
| 129 | +- Output gradients are overwritten. They do not require initialization and are not accumulated into existing output tensor values. | ||
| 130 | +- Computation is deterministic by default. | ||
| 131 | + | ||
| 132 | +For ACLNN calls, optional parameters must satisfy the following requirements: | ||
| 133 | + | ||
| 134 | +| Feature | When enabled | When omitted | | ||
| 135 | +| :--- | :--- | :--- | | ||
| 136 | +| Injection branch | `wGate`, `gradInject`, `inject`, and `dwGate` must all be supplied | All four must be `nullptr` | | ||
| 137 | +| Normalization scaling | `gamma` and `dgamma` must both be supplied | Both must be `nullptr`; the scale is 1 | | ||
| 138 | + | ||
| 139 | +The two groups of optional parameters are independent. `nullptr` omits the corresponding feature; a placeholder tensor with shape `[0]` cannot be used instead. | ||
| 140 | + | ||
| 141 | +## Calling the Operator | ||
| 142 | + | ||
| 143 | +| Method | Example | Description | | ||
| 144 | +| :--- | :--- | :--- | | ||
| 145 | +| aclnn call | [Interface example](./docs/aclnnTextGatedResidualGrad.md#调用示例) | Create input and output tensors, then call the two-stage interface to prepare and execute the computation. | | ||
| @@ -0,0 +1,381 @@ | |||
| 1 | +# aclnnTextGatedResidualGrad | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +<!-- npu="950" id1 --> | ||
| 6 | +- <term>Ascend 950PR&950DT系列产品</term>:支持 | ||
| 7 | +<!-- end id1 --> | ||
| 8 | +<!-- npu="A3" id2 --> | ||
| 9 | +- <term>Atlas A3系列产品</term>:支持 | ||
| 10 | +<!-- end id2 --> | ||
| 11 | +<!-- npu="910b" id3 --> | ||
| 12 | +- <term>Atlas A2系列产品</term>:支持 | ||
| 13 | +<!-- end id3 --> | ||
| 14 | +<!-- npu="310b" id4 --> | ||
| 15 | +- <term>Atlas 200I/500 A2推理产品</term>:不支持 | ||
| 16 | +<!-- end id4 --> | ||
| 17 | +<!-- npu="310p" id5 --> | ||
| 18 | +- <term>Atlas推理系列产品</term>:不支持 | ||
| 19 | +<!-- end id5 --> | ||
| 20 | +<!-- npu="910" id6 --> | ||
| 21 | +- <term>Atlas训练系列产品</term>:不支持 | ||
| 22 | +<!-- end id6 --> | ||
| 23 | + | ||
| 24 | +## 功能说明 | ||
| 25 | + | ||
| 26 | +`TextGatedResidualGrad` 是 `TextGatedResidual` 的反向算子。根据混合输出和注入输出的上游梯度,以及前向保存的张量,计算输入 `x` 和权重 `wDown`、`wUp`、`wGate`、`gamma` 的梯度。 | ||
| 27 | + | ||
| 28 | +记 $B$ 为批大小,$S$ 为序列长度,$C$ 为通道数,$H$ 为每通道的特征数,$R$ 为下投影维度,$D=C\times H$。$\odot$ 表示逐元素乘法,$@$ 表示矩阵乘法,$\sigma$ 表示 Sigmoid 函数。 | ||
| 29 | + | ||
| 30 | +对应的前向计算为: | ||
| 31 | + | ||
| 32 | +$$ | ||
| 33 | +\begin{aligned} | ||
| 34 | +\mathrm{invRms}_{b,s,c} &= \left(\frac{1}{H}\sum_{j=0}^{H-1}x_{b,s,c,j}^{2}+\epsilon\right)^{-1/2} \\ | ||
| 35 | +\mathrm{xNorm} &= x\odot\mathrm{invRms}\odot(1+\gamma) \\ | ||
| 36 | +\mathrm{downPreAct} &= \mathrm{xNorm}@\mathrm{wDown}^{T} \\ | ||
| 37 | +\mathrm{act} &= \mathrm{SiLU}(\mathrm{downPreAct}/C) \\ | ||
| 38 | +\mathrm{up} &= \mathrm{act}@\mathrm{wUp}^{T} \\ | ||
| 39 | +\mathrm{mixed}_{b,s,j} &= \frac{1}{C}\sum_{c=0}^{C-1}\mathrm{xNorm}_{b,s,c,j}\,\sigma(\mathrm{up}_{b,s,c,j}) \\ | ||
| 40 | +\mathrm{inject} &= 2\sigma\!\left((\mathrm{xNorm}@\mathrm{wGate}^{T})/C\right) | ||
| 41 | +\end{aligned} | ||
| 42 | +$$ | ||
| 43 | + | ||
| 44 | +其中,归一化及通道求和时将最后一维 $D$ 视为 $[C,H]$,矩阵乘法时仍使用最后一维 $D$。`invRms` 在每个通道的 $H$ 个特征上广播,`gamma` 在 $B$、$S$ 维上广播。$\epsilon$ 是前向归一化使用的参数,本接口通过 `invRms` 接收对应的前向结果。 | ||
| 45 | + | ||
| 46 | +给定 `gradMixed` 和 `gradInject`,定义 | ||
| 47 | + | ||
| 48 | +$$ | ||
| 49 | +L=\sum_{b,s,j}\mathrm{gradMixed}_{b,s,j}\,\mathrm{mixed}_{b,s,j} | ||
| 50 | + +\sum_{b,s,c}\mathrm{gradInject}_{b,s,c}\,\mathrm{inject}_{b,s,c}. | ||
| 51 | +$$ | ||
| 52 | + | ||
| 53 | +本算子的输出为: | ||
| 54 | + | ||
| 55 | +$$ | ||
| 56 | +dx=\frac{\partial L}{\partial x},\quad | ||
| 57 | +dwDown=\frac{\partial L}{\partial wDown},\quad | ||
| 58 | +dwUp=\frac{\partial L}{\partial wUp},\quad | ||
| 59 | +dwGate=\frac{\partial L}{\partial wGate},\quad | ||
| 60 | +dgamma=\frac{\partial L}{\partial\gamma}. | ||
| 61 | +$$ | ||
| 62 | + | ||
| 63 | +`wGate` 缺省时不包含注入分支及其梯度;`gamma` 缺省时归一化缩放系数为 1,不输出 `dgamma`。`invRms`、`inject`、`downPreAct`、`up` 必须来自同一次前向计算,并与本次传入的输入、权重对应。 | ||
| 64 | + | ||
| 65 | +## 函数原型 | ||
| 66 | + | ||
| 67 | +本接口采用[两段式调用](../../../docs/zh/context/two_phase_api.md):先调用 `aclnnTextGatedResidualGradGetWorkspaceSize` 获取工作空间大小和执行器,再调用 `aclnnTextGatedResidualGrad` 执行计算。 | ||
| 68 | + | ||
| 69 | +```cpp | ||
| 70 | +aclnnStatus aclnnTextGatedResidualGradGetWorkspaceSize( | ||
| 71 | + const aclTensor* gradMixed, const aclTensor* x, const aclTensor* wDown, const aclTensor* wUp, | ||
| 72 | + const aclTensor* invRms, const aclTensor* downPreAct, const aclTensor* up, const aclTensor* gradInject, | ||
| 73 | + const aclTensor* wGate, const aclTensor* gamma, const aclTensor* inject, int64_t channels, aclTensor* dx, | ||
| 74 | + aclTensor* dwDown, aclTensor* dwUp, aclTensor* dwGate, aclTensor* dgamma, uint64_t* workspaceSize, | ||
| 75 | + aclOpExecutor** executor); | ||
| 76 | + | ||
| 77 | +aclnnStatus aclnnTextGatedResidualGrad(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, | ||
| 78 | + aclrtStream stream); | ||
| 79 | +``` | ||
| 80 | + | ||
| 81 | +## aclnnTextGatedResidualGradGetWorkspaceSize | ||
| 82 | + | ||
| 83 | +- **参数说明** | ||
| 84 | + | ||
| 85 | +| 参数名 | 输入/输出 | 描述 | 使用说明 | 数据类型 | 数据格式 | shape | 非连续 Tensor | | ||
| 86 | +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :---: | | ||
| 87 | +| gradMixed(const aclTensor*) | 输入 | 混合输出 mixed 的上游梯度。 | 与 x 数据类型一致。 | FLOAT16、BFLOAT16 | ND | [B,S,H] | √ | | ||
| 88 | +| x(const aclTensor*) | 输入 | 前向输入。 | D=C*H。 | FLOAT16、BFLOAT16 | ND | [B,S,D] | √ | | ||
| 89 | +| wDown(const aclTensor*) | 输入 | 下投影权重。 | 与 x 数据类型一致。 | FLOAT16、BFLOAT16 | ND | [R,D] | √ | | ||
| 90 | +| wUp(const aclTensor*) | 输入 | 上投影权重。 | 与 x 数据类型一致。 | FLOAT16、BFLOAT16 | ND | [D,R] | √ | | ||
| 91 | +| invRms(const aclTensor*) | 输入 | 前向保存的各通道均方根倒数。 | 对应前向的归一化结果,包含前向 epsilon 的作用。 | FLOAT32 | ND | [B,S,C] | √ | | ||
| 92 | +| downPreAct(const aclTensor*) | 输入 | 前向保存的下投影结果 xNorm@wDownᵀ。 | 保存未除以 C、未经过 SiLU 的结果;与 x 数据类型一致。 | FLOAT16、BFLOAT16 | ND | [B,S,R] | √ | | ||
| 93 | +| up(const aclTensor*) | 输入 | 前向保存的上投影结果 act@wUpᵀ。 | 保存 Sigmoid 之前的值;与 x 数据类型一致。 | FLOAT16、BFLOAT16 | ND | [B,S,D] | √ | | ||
| 94 | +| gradInject(const aclTensor*) | 可选输入 | 注入输出 inject 的上游梯度。 | 与 x 数据类型一致;与 wGate、inject、dwGate 同时提供或同时缺省。 | FLOAT16、BFLOAT16 | ND | [B,S,C] | √ | | ||
| 95 | +| wGate(const aclTensor*) | 可选输入 | 注入分支权重。 | 与 x 数据类型一致;与 gradInject、inject、dwGate 同时提供或同时缺省。 | FLOAT16、BFLOAT16 | ND | [C,D] | √ | | ||
| 96 | +| gamma(const aclTensor*) | 可选输入 | 归一化缩放权重,实际缩放系数为 1+gamma。 | 传入原始 gamma;与 dgamma 同时提供或同时缺省。 | FLOAT32 | ND | [D] | √ | | ||
| 97 | +| inject(const aclTensor*) | 可选输入 | 前向保存的注入输出 2*sigmoid((xNorm@wGateᵀ)/C)。 | 与 x 数据类型一致;与 wGate、gradInject、dwGate 同时提供或同时缺省。 | FLOAT16、BFLOAT16 | ND | [B,S,C] | √ | | ||
| 98 | +| channels(int64_t) | 输入 | 通道数 C。 | C 为正整数,C ≤ 20。 | INT64 | - | 标量 | - | | ||
| 99 | +| dx(aclTensor*) | 输出 | x 的梯度。 | shape、数据类型与 x 一致。 | 同 x | ND | [B,S,D] | √ | | ||
| 100 | +| dwDown(aclTensor*) | 输出 | wDown 的梯度。 | shape 和数据类型与 wDown 一致。 | FLOAT16、BFLOAT16 | ND | [R,D] | √ | | ||
| 101 | +| dwUp(aclTensor*) | 输出 | wUp 的梯度。 | shape 和数据类型与 wUp 一致。 | FLOAT16、BFLOAT16 | ND | [D,R] | √ | | ||
| 102 | +| dwGate(aclTensor*) | 可选输出 | wGate 的梯度。 | shape 和数据类型与 wGate 一致;与 wGate、gradInject、inject 同时提供或同时缺省。 | FLOAT16、BFLOAT16 | ND | [C,D] | √ | | ||
| 103 | +| dgamma(aclTensor*) | 可选输出 | gamma 的梯度。 | shape 与 gamma 一致;与 gamma 同时提供或同时缺省。 | FLOAT32 | ND | [D] | √ | | ||
| 104 | +| workspaceSize(uint64_t*) | 输出 | 所需工作空间的字节数。 | 不能为空指针;按返回值申请 Device 内存。 | - | - | - | - | | ||
| 105 | +| executor(aclOpExecutor**) | 输出 | 本次调用的执行器。 | 不能为空指针;用于第二段接口。 | - | - | - | - | | ||
| 106 | + | ||
| 107 | +- **返回值** | ||
| 108 | + | ||
| 109 | +返回 `aclnnStatus`,参见 [aclnn 返回码](../../../docs/zh/context/aclnn_return_code.md)。 | ||
| 110 | + | ||
| 111 | +| 返回值 | 错误码 | 描述 | | ||
| 112 | +| :--- | ---: | :--- | | ||
| 113 | +| ACLNN_SUCCESS | 0 | 参数校验及执行准备成功。 | | ||
| 114 | +| ACLNN_ERR_PARAM_NULLPTR | 161001 | 必选 Tensor、workspaceSize 或 executor 为空指针,或可选参数未按要求成组提供。 | | ||
| 115 | +| ACLNN_ERR_PARAM_INVALID | 161002 | Tensor 的数据类型、维度或 shape 不符合参数表;channels 不在 [1,20] 范围内或不能整除 D;R 不在 [1,640] 范围内;B、S 为负数或 B*S 超出 INT64 表示范围。 | | ||
| 116 | +| ACLNN_ERR_INNER_CREATE_EXECUTOR | 561101 | 执行器创建失败。 | | ||
| 117 | +| ACLNN_ERR_INNER_NULLPTR | 561103 | 请求的形状组合不满足规格约束,或计算所需 Tensor 创建失败。 | | ||
| 118 | + | ||
| 119 | +## aclnnTextGatedResidualGrad | ||
| 120 | + | ||
| 121 | +- **参数说明** | ||
| 122 | + | ||
| 123 | +| 参数名 | 输入/输出 | 描述 | | ||
| 124 | +| :--- | :--- | :--- | | ||
| 125 | +| workspace(void*) | 输入 | Device 侧工作空间地址;workspaceSize 为 0 时可传入 nullptr。 | | ||
| 126 | +| workspaceSize(uint64_t) | 输入 | 第一段接口返回的工作空间字节数。 | | ||
| 127 | +| executor(aclOpExecutor*) | 输入 | 第一段接口返回的执行器。 | | ||
| 128 | +| stream(aclrtStream) | 输入 | 执行计算的 Stream。 | | ||
| 129 | + | ||
| 130 | +- **返回值** | ||
| 131 | + | ||
| 132 | +返回 `aclnnStatus`,参见 [aclnn 返回码](../../../docs/zh/context/aclnn_return_code.md)。 | ||
| 133 | + | ||
| 134 | +| 返回值 | 错误码 | 描述 | | ||
| 135 | +| :--- | ---: | :--- | | ||
| 136 | +| ACLNN_SUCCESS | 0 | 计算任务提交成功。 | | ||
| 137 | +| ACLNN_ERR_INNER | 561000 | 计算任务提交失败。 | | ||
| 138 | + | ||
| 139 | +第二段接口异步提交计算。读取输出前,应调用 `aclrtSynchronizeStream` 等待任务完成并检查其返回值。 | ||
| 140 | + | ||
| 141 | +## 约束说明 | ||
| 142 | + | ||
| 143 | +- `C`、`H`、`R` 为正整数;`H`、`R` 均须为 16 的整数倍。 | ||
| 144 | + | ||
| 145 | +通道数须满足 `C ≤ 20`。 | ||
| 146 | + | ||
| 147 | +`H` 的取值范围按产品确定。令 | ||
| 148 | + | ||
| 149 | +<!-- npu="950" id7 --> | ||
| 150 | +- <term>Ascend 950PR&950DT系列产品</term>: | ||
| 151 | + | ||
| 152 | + $$ | ||
| 153 | + K = 62448-16\left\lceil C/8\right\rceil | ||
| 154 | + $$ | ||
| 155 | + | ||
| 156 | +<!-- end id7 --> | ||
| 157 | +<!-- npu="A3,910b" id8 --> | ||
| 158 | +- <term>Atlas A2系列产品</term>、<term>Atlas A3系列产品</term>: | ||
| 159 | + | ||
| 160 | + $$ | ||
| 161 | + K = 39664-16\left\lceil C/8\right\rceil | ||
| 162 | + $$ | ||
| 163 | + | ||
| 164 | +<!-- end id8 --> | ||
| 165 | + | ||
| 166 | +`H`、`R` 须同时满足: | ||
| 167 | + | ||
| 168 | +$$ | ||
| 169 | +\boxed{ | ||
| 170 | +\begin{aligned} | ||
| 171 | +13H &\le K,\\ | ||
| 172 | +3H+8R &\le K,\\ | ||
| 173 | +7H+6R &\le K. | ||
| 174 | +\end{aligned} | ||
| 175 | +} | ||
| 176 | +$$ | ||
| 177 | + | ||
| 178 | +因此,给定 `C` 后,`H` 的上限为 | ||
| 179 | + | ||
| 180 | +$$ | ||
| 181 | +H_{\max}=16\left\lfloor\frac{K}{208}\right\rfloor. | ||
| 182 | +$$ | ||
| 183 | + | ||
| 184 | +`R` 须同时满足上述关系式和 `R ≤ 640`。 | ||
| 185 | + | ||
| 186 | +其中,$\lceil\cdot\rceil$ 表示向上取整,$\lfloor\cdot\rfloor$ 表示向下取整。上述关系适用于 FLOAT16、BFLOAT16,以及所有合法的可选参数组合。 | ||
| 187 | + | ||
| 188 | +例如,`C=4、H=2560、R=320` 适用于上述三类产品。其他 `C/H/R` 组合须满足上述约束。调用时仍需通过第一段接口 `aclnnTextGatedResidualGradGetWorkspaceSize` 完成参数校验,并按返回的 `workspaceSize` 申请内存。 | ||
| 189 | + | ||
| 190 | +- 所有 FLOAT16/BFLOAT16 输入以及 `dx`、`dwDown`、`dwUp`、`dwGate` 的数据类型必须一致;各权重梯度与对应权重的数据类型相同。`invRms`、`gamma` 和 `dgamma` 为 FLOAT32。 | ||
| 191 | +- 支持非连续输入 Tensor。输入输出的 shape 必须符合参数表,同名维度的大小必须一致。 | ||
| 192 | +- 支持 `B=0` 或 `S=0`:`dx` 为空,已提供的非空权重梯度和 `dgamma` 全部置零,其余参数仍须满足上述约束。 | ||
| 193 | +- 输出梯度覆盖写入,调用前无需初始化,也不会累加到输出 Tensor 的原有数据中。 | ||
| 194 | +- 默认执行确定性计算。 | ||
| 195 | + | ||
| 196 | +可选参数的使用方式如下: | ||
| 197 | + | ||
| 198 | +| 功能 | 提供时 | 缺省时 | | ||
| 199 | +| :--- | :--- | :--- | | ||
| 200 | +| 注入分支 | `wGate`、`gradInject`、`inject`、`dwGate` 四者必须同时提供 | 四者必须全部传入 `nullptr` | | ||
| 201 | +| 归一化缩放 | `gamma`、`dgamma` 必须同时提供 | 两者必须全部传入 `nullptr`,缩放系数取 1 | | ||
| 202 | + | ||
| 203 | +两组可选参数相互独立。`nullptr` 表示省略该功能,不能用 shape 为 `[0]` 的占位 Tensor 代替。 | ||
| 204 | + | ||
| 205 | +## 调用示例 | ||
| 206 | + | ||
| 207 | +以下示例使用 BFLOAT16,`B=1、S=2、C=4、H=16、R=16`,同时计算注入分支和 gamma 梯度。 | ||
| 208 | +输入 `x`、全部权重及 `gamma` 为 0,前向取 `epsilon=1e-6`,因此 `invRms=1000`、`downPreAct=0`、`up=0`、`inject=1`;两个上游梯度均为 1。 | ||
| 209 | +预期 `dx` 的所有元素为 125,`dwDown`、`dwUp`、`dwGate`、`dgamma` 的所有元素为 0。 | ||
| 210 | + | ||
| 211 | +编译与运行方式参见[编译与运行样例](../../../docs/zh/context/compile_and_run_sample.md)。请根据安装方式设置本算子的头文件和库搜索路径。 | ||
| 212 | + | ||
| 213 | +```cpp | ||
| 214 | +#include <cstdint> | ||
| 215 | +#include <cstdio> | ||
| 216 | +#include <cstring> | ||
| 217 | +#include <vector> | ||
| 218 | +#include "acl/acl.h" | ||
| 219 | +#include "aclnnop/aclnn_text_gated_residual_grad.h" | ||
| 220 | + | ||
| 221 | +namespace { | ||
| 222 | +constexpr int32_t DEVICE_ID = 0; | ||
| 223 | +constexpr int64_t B = 1; | ||
| 224 | +constexpr int64_t S = 2; | ||
| 225 | +constexpr int64_t C = 4; | ||
| 226 | +constexpr int64_t H = 16; | ||
| 227 | +constexpr int64_t R = 16; | ||
| 228 | +constexpr int64_t D = C * H; | ||
| 229 | +constexpr uint16_t BF16_ZERO = 0x0000; | ||
| 230 | +constexpr uint16_t BF16_ONE = 0x3F80; | ||
| 231 | +constexpr uint32_t BF16_SHIFT = 16; | ||
| 232 | +constexpr float SAVED_INV_RMS = 1000.0F; | ||
| 233 | + | ||
| 234 | +bool Check(int status, const char* action) | ||
| 235 | +{ | ||
| 236 | + if (status != ACL_SUCCESS) { | ||
| 237 | + std::printf("%s failed: %d\n", action, status); | ||
| 238 | + return false; | ||
| 239 | + } | ||
| 240 | + return true; | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +struct Resources { | ||
| 244 | + bool initialized = false; | ||
| 245 | + bool deviceSet = false; | ||
| 246 | + aclrtStream stream = nullptr; | ||
| 247 | + std::vector<aclTensor*> tensors; | ||
| 248 | + std::vector<void*> buffers; | ||
| 249 | + | ||
| 250 | + ~Resources() | ||
| 251 | + { | ||
| 252 | + if (stream != nullptr) { | ||
| 253 | + aclrtSynchronizeStream(stream); | ||
| 254 | + } | ||
| 255 | + for (auto* tensor : tensors) { | ||
| 256 | + aclDestroyTensor(tensor); | ||
| 257 | + } | ||
| 258 | + for (auto* buffer : buffers) { | ||
| 259 | + aclrtFree(buffer); | ||
| 260 | + } | ||
| 261 | + if (stream != nullptr) { | ||
| 262 | + aclrtDestroyStream(stream); | ||
| 263 | + } | ||
| 264 | + if (deviceSet) { | ||
| 265 | + aclrtResetDevice(DEVICE_ID); | ||
| 266 | + } | ||
| 267 | + if (initialized) { | ||
| 268 | + aclFinalize(); | ||
| 269 | + } | ||
| 270 | + } | ||
| 271 | +}; | ||
| 272 | + | ||
| 273 | +template <typename T> | ||
| 274 | +aclTensor* CreateTensor(Resources& resources, const std::vector<int64_t>& shape, aclDataType dtype, T value, | ||
| 275 | + bool isInput, void** outputAddress = nullptr) | ||
| 276 | +{ | ||
| 277 | + int64_t count = 1; | ||
| 278 | + std::vector<int64_t> strides(shape.size()); | ||
| 279 | + for (size_t axis = shape.size(); axis > 0; --axis) { | ||
| 280 | + strides[axis - 1] = count; | ||
| 281 | + count *= shape[axis - 1]; | ||
| 282 | + } | ||
| 283 | + const size_t bytes = static_cast<size_t>(count) * sizeof(T); | ||
| 284 | + void* address = nullptr; | ||
| 285 | + if (!Check(aclrtMalloc(&address, bytes, ACL_MEM_MALLOC_HUGE_FIRST), "aclrtMalloc")) { | ||
| 286 | + return nullptr; | ||
| 287 | + } | ||
| 288 | + resources.buffers.push_back(address); | ||
| 289 | + if (isInput) { | ||
| 290 | + std::vector<T> host(static_cast<size_t>(count), value); | ||
| 291 | + if (!Check(aclrtMemcpy(address, bytes, host.data(), bytes, ACL_MEMCPY_HOST_TO_DEVICE), "aclrtMemcpy")) { | ||
| 292 | + return nullptr; | ||
| 293 | + } | ||
| 294 | + } | ||
| 295 | + auto* tensor = aclCreateTensor(shape.data(), shape.size(), dtype, strides.data(), 0, ACL_FORMAT_ND, shape.data(), | ||
| 296 | + shape.size(), address); | ||
| 297 | + if (tensor == nullptr) { | ||
| 298 | + std::printf("aclCreateTensor failed\n"); | ||
| 299 | + return nullptr; | ||
| 300 | + } | ||
| 301 | + resources.tensors.push_back(tensor); | ||
| 302 | + if (outputAddress != nullptr) { | ||
| 303 | + *outputAddress = address; | ||
| 304 | + } | ||
| 305 | + return tensor; | ||
| 306 | +} | ||
| 307 | +} // namespace | ||
| 308 | + | ||
| 309 | +int main() | ||
| 310 | +{ | ||
| 311 | + Resources resources; | ||
| 312 | + if (!Check(aclInit(nullptr), "aclInit")) { | ||
| 313 | + return 1; | ||
| 314 | + } | ||
| 315 | + resources.initialized = true; | ||
| 316 | + if (!Check(aclrtSetDevice(DEVICE_ID), "aclrtSetDevice")) { | ||
| 317 | + return 1; | ||
| 318 | + } | ||
| 319 | + resources.deviceSet = true; | ||
| 320 | + if (!Check(aclrtCreateStream(&resources.stream), "aclrtCreateStream")) { | ||
| 321 | + return 1; | ||
| 322 | + } | ||
| 323 | + | ||
| 324 | + auto* gradMixed = CreateTensor(resources, {B, S, H}, ACL_BF16, BF16_ONE, true); | ||
| 325 | + auto* gradInject = CreateTensor(resources, {B, S, C}, ACL_BF16, BF16_ONE, true); | ||
| 326 | + auto* x = CreateTensor(resources, {B, S, D}, ACL_BF16, BF16_ZERO, true); | ||
| 327 | + auto* wDown = CreateTensor(resources, {R, D}, ACL_BF16, BF16_ZERO, true); | ||
| 328 | + auto* wUp = CreateTensor(resources, {D, R}, ACL_BF16, BF16_ZERO, true); | ||
| 329 | + auto* wGate = CreateTensor(resources, {C, D}, ACL_BF16, BF16_ZERO, true); | ||
| 330 | + auto* gamma = CreateTensor(resources, {D}, ACL_FLOAT, 0.0F, true); | ||
| 331 | + auto* invRms = CreateTensor(resources, {B, S, C}, ACL_FLOAT, SAVED_INV_RMS, true); | ||
| 332 | + auto* inject = CreateTensor(resources, {B, S, C}, ACL_BF16, BF16_ONE, true); | ||
| 333 | + auto* downPreAct = CreateTensor(resources, {B, S, R}, ACL_BF16, BF16_ZERO, true); | ||
| 334 | + auto* up = CreateTensor(resources, {B, S, D}, ACL_BF16, BF16_ZERO, true); | ||
| 335 | + | ||
| 336 | + void* dxAddress = nullptr; | ||
| 337 | + auto* dx = CreateTensor(resources, {B, S, D}, ACL_BF16, BF16_ZERO, false, &dxAddress); | ||
| 338 | + auto* dwDown = CreateTensor(resources, {R, D}, ACL_BF16, BF16_ZERO, false); | ||
| 339 | + auto* dwUp = CreateTensor(resources, {D, R}, ACL_BF16, BF16_ZERO, false); | ||
| 340 | + auto* dwGate = CreateTensor(resources, {C, D}, ACL_BF16, BF16_ZERO, false); | ||
| 341 | + auto* dgamma = CreateTensor(resources, {D}, ACL_FLOAT, 0.0F, false); | ||
| 342 | + for (auto* tensor : {gradMixed, gradInject, x, wDown, wUp, wGate, gamma, invRms, inject, downPreAct, up, dx, dwDown, | ||
| 343 | + dwUp, dwGate, dgamma}) { | ||
| 344 | + if (tensor == nullptr) { | ||
| 345 | + return 1; | ||
| 346 | + } | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + uint64_t workspaceSize = 0; | ||
| 350 | + aclOpExecutor* executor = nullptr; | ||
| 351 | + auto status = aclnnTextGatedResidualGradGetWorkspaceSize(gradMixed, x, wDown, wUp, invRms, downPreAct, up, | ||
| 352 | + gradInject, wGate, gamma, inject, C, dx, dwDown, dwUp, | ||
| 353 | + dwGate, dgamma, &workspaceSize, &executor); | ||
| 354 | + if (!Check(status, "aclnnTextGatedResidualGradGetWorkspaceSize")) { | ||
| 355 | + return 1; | ||
| 356 | + } | ||
| 357 | + void* workspace = nullptr; | ||
| 358 | + if (workspaceSize > 0) { | ||
| 359 | + if (!Check(aclrtMalloc(&workspace, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST), "aclrtMalloc workspace")) { | ||
| 360 | + return 1; | ||
| 361 | + } | ||
| 362 | + resources.buffers.push_back(workspace); | ||
| 363 | + } | ||
| 364 | + if (!Check(aclnnTextGatedResidualGrad(workspace, workspaceSize, executor, resources.stream), | ||
| 365 | + "aclnnTextGatedResidualGrad") || | ||
| 366 | + !Check(aclrtSynchronizeStream(resources.stream), "aclrtSynchronizeStream")) { | ||
| 367 | + return 1; | ||
| 368 | + } | ||
| 369 | + | ||
| 370 | + uint16_t first = 0; | ||
| 371 | + if (!Check(aclrtMemcpy(&first, sizeof(first), dxAddress, sizeof(first), ACL_MEMCPY_DEVICE_TO_HOST), | ||
| 372 | + "copy dx to host")) { | ||
| 373 | + return 1; | ||
| 374 | + } | ||
| 375 | + const uint32_t bits = static_cast<uint32_t>(first) << BF16_SHIFT; | ||
| 376 | + float value = 0.0F; | ||
| 377 | + std::memcpy(&value, &bits, sizeof(value)); | ||
| 378 | + std::printf("dx[0] = %.1f (expected 125.0)\n", value); | ||
| 379 | + return 0; | ||
| 380 | +} | ||
| 381 | +``` | ||