开发者
下载
[object Object]

[object Object][object Object]
  • [object Object]Ascend 950PR/Ascend 950DT[object Object]:支持
[object Object][object Object]
  • [object Object]Atlas A3 训练系列产品/Atlas A3 推理系列产品[object Object]:不支持
[object Object][object Object]
  • [object Object]Atlas A2 训练系列产品/Atlas A2 推理系列产品[object Object]:不支持
[object Object][object Object]
  • [object Object]Atlas 200I/500 A2 推理产品[object Object]:不支持
[object Object][object Object]
  • [object Object]Atlas 推理系列产品[object Object]:不支持
[object Object][object Object]
  • [object Object]Atlas 训练系列产品[object Object]:不支持
[object Object][object Object][object Object]

SwigluGroupQuant算子实现SwiGLU激活函数与分组量化融合计算。支持四种量化模式:

  • quant_mode=0:Block Quant(FP8块量化,固定128元素分组)
  • quant_mode=1:MX Quant(FP8 MX量化,固定32元素分组)
  • quant_mode=2:HiFp8 Static Quant(HiFp8静态量化)
  • quant_mode=3:HiFp8 Dynamic Quant(HiFp8动态量化)
[object Object][object Object]
[object Object]
[object Object]

当提供[object Object]时,用于动态计算实际处理的token数量:

group_sum=g=0G1group_index[g]\text{group\_sum} = \sum_{g=0}^{G-1} \text{group\_index}[g] real_bs=min(group_sum,N)\text{real\_bs} = \min(\text{group\_sum}, N)

其中:

  • GG为MoE专家分组数
  • NN为输入张量的第一维(预设batch size)
  • 后续所有步骤仅处理前real_bs\text{real\_bs}行数据

MoE场景说明:在MoE推理中,不同专家可能处理不同数量的token,group_index允许动态调整处理范围,避免处理空数据。

[object Object]

输入张量xRN×D\mathbf{x} \in \mathbb{R}^{N \times D}沿最后一维切分为两部分:

x0[n,d]=x[n,d],d[0,D/2)\mathbf{x}_0[n, d] = \mathbf{x}[n, d], \quad d \in [0, D/2) x1[n,d]=x[n,d+D/2],d[0,D/2)\mathbf{x}_1[n, d] = \mathbf{x}[n, d + D/2], \quad d \in [0, D/2) [object Object]

[object Object]时,对输入进行限制:

x0[n,d]=min(x0[n,d],c)\mathbf{x}_0'[n, d] = \min(\mathbf{x}_0[n, d], c) x1[n,d]=min(max(x1[n,d],c),c)\mathbf{x}_1'[n, d] = \min(\max(\mathbf{x}_1[n, d], -c), c)

其中cc[object Object]

Clamp的作用

  • x0\mathbf{x}_0(门控分支)限制为正值范围[0,c][0, c],防止sigmoid梯度消失
  • x1\mathbf{x}_1(线性分支)限制为对称范围[c,c][-c, c],防止数值溢出
[object Object]

SwiGLU激活函数定义(逐元素计算):

yswiglu[n,d]=Swish(x0[n,d])x1[n,d]\mathbf{y}_{\text{swiglu}}[n, d] = \text{Swish}(\mathbf{x}_0'[n, d]) \cdot \mathbf{x}_1'[n, d]

其中Swish函数:

Swish(z)=zσ(z)=z11+ez\text{Swish}(z) = z \cdot \sigma(z) = z \cdot \frac{1}{1 + e^{-z}}

完整计算步骤分解

t1[n,d]=x0[n,d](neg)t2[n,d]=et1[n,d]=ex0[n,d](exp)t3[n,d]=t2[n,d]+1=1+ex0[n,d](add)t4[n,d]=x0[n,d]t3[n,d]=Swish(x0[n,d])(div)yswiglu[n,d]=t4[n,d]x1[n,d](mul)\begin{aligned} t_1[n, d] &= -\mathbf{x}_0'[n, d] \quad \text{(neg)} \\ t_2[n, d] &= e^{t_1[n, d]} = e^{-\mathbf{x}_0'[n, d]} \quad \text{(exp)} \\ t_3[n, d] &= t_2[n, d] + 1 = 1 + e^{-\mathbf{x}_0'[n, d]} \quad \text{(add)} \\ t_4[n, d] &= \frac{\mathbf{x}_0'[n, d]}{t_3[n, d]} = \text{Swish}(\mathbf{x}_0'[n, d]) \quad \text{(div)} \\ \mathbf{y}_{\text{swiglu}}[n, d] &= t_4[n, d] \cdot \mathbf{x}_1'[n, d] \quad \text{(mul)} \end{aligned} [object Object]

当提供[object Object]时,对SwiGLU输出进行加权:

yweighted[n,d]=yswiglu[n,d]w[n]\mathbf{y}_{\text{weighted}}[n, d] = \mathbf{y}_{\text{swiglu}}[n, d] \cdot w[n]

其中w[n]w[n]为第nn个token的weight值。

MoE场景:weight来自专家路由器的softmax输出,表示该token对当前专家的权重。

[object Object]
[object Object]

分组划分:将输出沿最后一维按128元素为一组划分:

y=[g0,g1,,gK],K=D/2/128\mathbf{y} = [\mathbf{g}_0, \mathbf{g}_1, \ldots, \mathbf{g}_K], \quad K = \lceil D/2 / 128 \rceil

每个组giRN×128\mathbf{g}_i \in \mathbb{R}^{N \times 128}

非有限值屏蔽与绝对值计算

z[n,j]=yweighted[n,j]0(生成零张量)mfinite[n,j]=(z[n,j]=z[n,j])yabs[n,j]={yweighted[n,j],mfinite[n,j]0,otherwise\begin{aligned} \mathbf{z}[n, j] &= \mathbf{y}_{\text{weighted}}[n, j] \cdot 0 \quad \text{(生成零张量)} \\ \mathbf{m}_{\text{finite}}[n, j] &= (\mathbf{z}[n, j] = \mathbf{z}[n, j]) \\ \mathbf{y}_{\text{abs}}[n, j] &= \begin{cases} |\mathbf{y}_{\text{weighted}}[n, j]|, & \mathbf{m}_{\text{finite}}[n, j] \\ 0, & \text{otherwise} \end{cases} \end{aligned}

屏蔽原理:NaN的特性是[object Object];同时[object Object]也会得到NaN,因此该步骤在计算amax时屏蔽NaN和Inf。

Scale计算

对于第ii个组(包含128个连续元素):

ai=maxj=0127yabs[j]a_i = \max_{j=0}^{127} \mathbf{y}_{\text{abs}}[j] a^i=max(ai,104)\hat{a}_i = \max(a_i, 10^{-4}) siraw=a^iMfp8s_i^{\text{raw}} = \frac{\hat{a}_i}{M_{\text{fp8}}}

其中Mfp8M_{\text{fp8}}取值:

  • FP8 E4M3FN:Mfp8=448.0M_{\text{fp8}} = 448.0
  • FP8 E5M2:Mfp8=57344.0M_{\text{fp8}} = 57344.0

Scale输出与InvScale计算

[object Object]时:

si=siraw,InvScalei=Mfp8a^i=1sis_i = s_i^{\text{raw}}, \quad \text{InvScale}_i = \frac{M_{\text{fp8}}}{\hat{a}_i} = \frac{1}{s_i}

[object Object]时,将scale向上取整到2的幂:

ei=log2(siraw)e_i = \lceil \log_2(s_i^{\text{raw}}) \rceil si=2ei,InvScalei=2eis_i = 2^{e_i}, \quad \text{InvScale}_i = 2^{-e_i}

其中sis_i写入FLOAT32类型的scale输出。

量化计算

yscaled[n,j]=yweighted[n,j]InvScalei,jgroup i\mathbf{y}_{\text{scaled}}[n, j] = \mathbf{y}_{\text{weighted}}[n, j] \cdot \text{InvScale}_i, \quad j \in \text{group } i

yscaled[n,j]\mathbf{y}_{\text{scaled}}[n,j] 为NaN或Inf,实现会使用原始 yweighted[n,j]\mathbf{y}_{\text{weighted}}[n,j] 作为FP8 cast输入:

ycast_in[n,j]={yscaled[n,j],yscaled[n,j] is finiteyweighted[n,j],otherwise\mathbf{y}_{\text{cast\_in}}[n, j] = \begin{cases} \mathbf{y}_{\text{scaled}}[n, j], & \mathbf{y}_{\text{scaled}}[n, j] \text{ is finite} \\ \mathbf{y}_{\text{weighted}}[n, j], & \text{otherwise} \end{cases} yquant[n,j]=cast_fp8_rint(ycast_in[n,j])\mathbf{y}_{\text{quant}}[n, j] = \text{cast\_fp8\_rint}(\mathbf{y}_{\text{cast\_in}}[n, j])

其中[object Object]为FP32到FP8的类型转换,采用**RINT(就近舍入)**模式。


[object Object]

MX量化原理:采用E8M0 Scale + FP8 Data的组合。

分组方式:每32元素为一组:

y=[g0,g1,,gK],giR32\mathbf{y} = [\mathbf{g}_0, \mathbf{g}_1, \ldots, \mathbf{g}_K], \quad \mathbf{g}_i \in \mathbb{R}^{32}

Amax计算

ai=maxj=031gi[j]a_i = \max_{j=0}^{31} |\mathbf{g}_i[j]| a^i=max(ai,104)\hat{a}_i = \max(a_i, 10^{-4})

原始Scale计算

siraw=a^iMfp8s_i^{\text{raw}} = \frac{\hat{a}_i}{M_{\text{fp8}}}

其中Mfp8M_{\text{fp8}}取值:

  • FP8 E4M3FN:Mfp8=448.0M_{\text{fp8}} = 448.0
  • FP8 E5M2:Mfp8=57344.0M_{\text{fp8}} = 57344.0

quant_mode=1仅支持[object Object],将原始scale向上取整到2的幂:

ei=log2(siraw)e_i = \lceil \log_2(s_i^{\text{raw}}) \rceil

等价于基于FP32位模式计算:

ei=E(siraw)127+1mantissa(siraw)0e_i = E(s_i^{\text{raw}}) - 127 + \mathbf{1}_{\text{mantissa}(s_i^{\text{raw}}) \ne 0}

E8M0 Scale编码

sie8m0=ei+127s_i^{\text{e8m0}} = e_i + 127

其中sie8m0s_i^{\text{e8m0}}写入FLOAT8_E8M0类型的scale输出,表示的实际scale值为2ei2^{e_i}

InvScale计算

InvScalei=2ei\text{InvScale}_i = 2^{-e_i}

量化计算

yquant[j]=cast_fp8_rint(yweighted[j]InvScalei),jgroup i\mathbf{y}_{\text{quant}}[j] = \text{cast\_fp8\_rint}\left(\mathbf{y}_{\text{weighted}}[j] \cdot \text{InvScale}_i\right), \quad j \in \text{group } i
[object Object]

静态量化说明:使用预先提供的[object Object]对加权后的SwiGLU输出进行缩放量化。

情况1:无GroupIndex(groupIndex为空):

yquant[n,d]=hif8_cast(yweighted[n,d]invScale[0]),n[0,N),d[0,D/2)\mathbf{y}_{\text{quant}}[n, d] = \text{hif8\_cast}\left(\mathbf{y}_{\text{weighted}}[n, d] \cdot \text{invScale}[0]\right), \quad n \in [0, N), \quad d \in [0, D/2)

其中[object Object]为HiFloat8类型转换函数。

情况2:有GroupIndex(groupIndex非空):

GG为MoE专家分组数,groupIndex[g]\text{groupIndex}[g]表示第gg个专家处理的token数量。

计算每个group的起止索引:

start(0)=0,end(g)=k=0ggroupIndex[k],start(g)=end(g1)\text{start}^{(0)} = 0, \quad \text{end}^{(g)} = \sum_{k=0}^{g} \text{groupIndex}[k], \quad \text{start}^{(g)} = \text{end}^{(g-1)}

对于第gg个group,使用对应的缩放因子invScale[g]\text{invScale}[g]进行量化:

yquant[n,d]=hif8_cast(yweighted[n,d]invScale[g]),n[start(g),end(g)),d[0,D/2)\mathbf{y}_{\text{quant}}[n, d] = \text{hif8\_cast}\left(\mathbf{y}_{\text{weighted}}[n, d] \cdot \text{invScale}[g]\right), \quad n \in [\text{start}^{(g)}, \text{end}^{(g)}), \quad d \in [0, D/2)

MoE场景说明:在MoE推理中,不同专家处理不同数量的token,groupIndex用于标识每个专家处理的token范围,invScale为每个专家预先计算的静态缩放因子。


[object Object]

动态量化说明:根据加权后的SwiGLU输出动态计算缩放因子进行量化。

情况1:无GroupIndex(groupIndex为空):

计算全局绝对值最大值:

amax=max(maxn[0,N),d[0,D/2)yweighted[n,d],ϵ)a_{\max} = \max\left(\max_{n \in [0, N), d \in [0, D/2)} |\mathbf{y}_{\text{weighted}}[n, d]|, \epsilon\right)

其中ϵ\epsilon为数值稳定性常数。

计算缩放因子:

s=amaxMhif8s = \frac{a_{\max}}{M_{\text{hif8}}}

其中Mhif8M_{\text{hif8}}[object Object],表示HiFloat8类型的最大有限值。

量化计算:

yquant[n,d]=hif8_cast(yweighted[n,d]s),n[0,N),d[0,D/2)\mathbf{y}_{\text{quant}}[n, d] = \text{hif8\_cast}\left(\frac{\mathbf{y}_{\text{weighted}}[n, d]}{s}\right), \quad n \in [0, N), \quad d \in [0, D/2)

其中[object Object]为HiFloat8类型转换函数。

情况2:有GroupIndex(groupIndex非空):

GG为MoE专家分组数,groupIndex[g]\text{groupIndex}[g]表示第gg个专家处理的token数量。

计算每个group的起止索引:

start(0)=0,end(g)=k=0ggroupIndex[k],start(g)=end(g1)\text{start}^{(0)} = 0, \quad \text{end}^{(g)} = \sum_{k=0}^{g} \text{groupIndex}[k], \quad \text{start}^{(g)} = \text{end}^{(g-1)}

对于第gg个group,提取对应的数据:

y(g)=yweighted[start(g):end(g),:]\mathbf{y}^{(g)} = \mathbf{y}_{\text{weighted}}[\text{start}^{(g)}:\text{end}^{(g)}, :]

计算该group的绝对值最大值:

amax(g)=max(maxn[start(g),end(g)),d[0,D/2)y(g)[n,d],ϵ)a_{\max}^{(g)} = \max\left(\max_{n \in [\text{start}^{(g)}, \text{end}^{(g)}), d \in [0, D/2)} |\mathbf{y}^{(g)}[n, d]|, \epsilon\right)

计算该group的缩放因子:

s(g)=amax(g)Mhif8s^{(g)} = \frac{a_{\max}^{(g)}}{M_{\text{hif8}}}

对该group进行量化:

yquant[n,d]=hif8_cast(yweighted[n,d]s(g)),n[start(g),end(g)),d[0,D/2)\mathbf{y}_{\text{quant}}[n, d] = \text{hif8\_cast}\left(\frac{\mathbf{y}_{\text{weighted}}[n, d]}{s^{(g)}}\right), \quad n \in [\text{start}^{(g)}, \text{end}^{(g)}), \quad d \in [0, D/2)

MoE场景说明:在MoE推理中,不同专家处理不同数量的token,groupIndex用于标识每个专家处理的token范围,每个group独立计算缩放因子以适应不同数据分布。

[object Object]

每个算子分为,必须先调用“aclnnSwigluGroupQuantGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnSwigluGroupQuant”接口执行计算。

[object Object]
[object Object]
[object Object]
  • 参数说明:

    [object Object]
  • 返回值:

    aclnnStatus:返回状态码,具体参见

    第一段接口完成入参校验,出现以下场景时报错:

    [object Object]
[object Object]
  • 参数说明:

    [object Object]
  • 返回值:

    aclnnStatus:返回状态码,具体参见

[object Object]
  • 确定性计算:aclnnSwigluGroupQuant默认确定性实现。

  • quantMode为0时,仅支持FP8输出,blockSize支持0或128。

  • quantMode为1时,支持FP8/FP4输出,blockSize支持0或32,roundScale必须为true。

  • quantMode为2或3时,支持HIFP8量化输出,dstType, blockSize和roundScale不生效。输入x的维度为[T, D]或[B, S, D],需满足以下规格约束:

    [object Object]undefined
  • dstType为FLOAT4_E2M1或FLOAT4_E1M2时,必须使用quantMode=1。

  • yScale的数据类型必须与quantMode匹配:quantMode=0或3时数据类型为FLOAT32,quantMode=1时数据类型为FLOAT8_E8M0。

[object Object]

示例代码如下,仅供参考,具体编译和执行过程请参考

[object Object]