| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 9 天前 | ||
| 9 天前 | ||
| 3 个月前 | ||
| 2 天前 | ||
| 2 天前 | ||
| 4 天前 | ||
| 2 天前 | ||
| 3 个月前 | ||
| 14 天前 |
MegaMoE
产品支持情况
| 产品 | 是否支持 |
|---|---|
| Ascend 950PR&950DT系列产品 | √ |
| Atlas A3系列产品 | √ |
| Atlas A2系列产品 | √ |
| Atlas 200I/500 A2推理产品 | × |
| Atlas推理系列产品 | × |
| Atlas训练系列产品 | × |
功能说明
-
算子功能:MegaMoE算子将MoE层的专家FFN的完整计算流程及前后数据通信(即 Dispatch + Linear1 + Activation + Linear2 + Combine)融合为单个算子,实现了通信和计算的掩盖。
-
计算公式:
-
输入:
- X∈RtotalNumTokens×hidden\mathbf{X} \in \mathbb{R}^{\text{totalNumTokens} \times \text{hidden}}:激活矩阵,对应入参
x。totalNumTokens\text{totalNumTokens} 是全局总 token 数,hidden\text{hidden} 是隐藏层维度。 - E∈ZtotalNumTokens×topK\mathbf{E} \in \mathbb{Z}^{\text{totalNumTokens} \times \text{topK}}:token 选择的专家编号矩阵,对应入参
topkIds。topK\text{topK} 是每个 token 选择的专家数量。 - G∈RtotalNumTokens×topK\mathbf{G} \in \mathbb{R}^{\text{totalNumTokens} \times \text{topK}}:token 选择的专家的门控权重矩阵,对应入参
topkWeights。 - W1moe∈RlocalMoeExpertNum×hidden×(2intermediateHidden)\mathbf{W}_1^{\mathrm{moe}} \in \mathbb{R}^{\text{localMoeExpertNum} \times \text{hidden} \times (2 \text{intermediateHidden})}:路由 MoE 专家的 Linear1 权重,对应入参
weight1的 MoE 专家部分。 - W2moe∈RlocalMoeExpertNum×intermediateHidden×hidden\mathbf{W}_2^{\mathrm{moe}} \in \mathbb{R}^{\text{localMoeExpertNum} \times \text{intermediateHidden} \times \text{hidden}}:路由 MoE 专家的 Linear2 权重,对应入参
weight2的 MoE 专家部分。 - W1shared∈RsharedExpertNumPerRank×hidden×(2intermediateHidden)\mathbf{W}_1^{\mathrm{shared}} \in \mathbb{R}^{\text{sharedExpertNumPerRank} \times \text{hidden} \times (2 \text{intermediateHidden})}:共享专家的 Linear1 权重,对应入参
sharedWeight1。 - W2shared∈RsharedExpertNumPerRank×intermediateHidden×hidden\mathbf{W}_2^{\mathrm{shared}} \in \mathbb{R}^{\text{sharedExpertNumPerRank} \times \text{intermediateHidden} \times \text{hidden}}:共享专家的 Linear2 权重,对应入参
sharedWeight2。
- X∈RtotalNumTokens×hidden\mathbf{X} \in \mathbb{R}^{\text{totalNumTokens} \times \text{hidden}}:激活矩阵,对应入参
-
输出:
- Y∈RtotalNumTokens×hidden\mathbf{Y} \in \mathbb{R}^{\text{totalNumTokens} \times \text{hidden}}:最终输出矩阵,对应出参
y。
- Y∈RtotalNumTokens×hidden\mathbf{Y} \in \mathbb{R}^{\text{totalNumTokens} \times \text{hidden}}:最终输出矩阵,对应出参
-
约定:
- ⋅⋅ 表示矩阵乘法,⊙⊙ 表示逐元素乘法。
- ⌊z⌉\left \lfloor z\right \rceil 表示将 zz 四舍五入到最近的整数,⌊z⌋\left \lfloor z\right \rfloor 表示将 zz 向下取整。
- ∣z∣|z| 表示取绝对值,max(z)\max(z) 表示取最大值。
- 全体 token 的集合为 {tokeni∣i∈{0,1,…,totalNumTokens−1}}\{ \text{token}_i \mid i \in \{0, 1, \dots, \text{totalNumTokens} - 1\} \}。
- tokeni\text{token}_i 的 token 表示(即隐藏状态向量)为 xi∈R1×hidden\mathbf{x}_i \in \mathbb{R}^{1 \times \text{hidden}},且 xi=X[i,:]\mathbf{x}_i = \mathbf{X}[i,:]。
- tokeni\text{token}_i 的专家索引为 ei,k=E[i,k],k∈{0,…,topK−1},ei,k∈{0,…,moeExpertNum−1}e_{i,k} = \mathbf{E}[i,k],\quad k \in \{0,\dots,\text{topK} - 1\},\quad e_{i,k} \in \{0,\dots,\text{moeExpertNum} - 1\}。
- Z4={x∈Z∣−8≤x≤7},Z8sym={x∈Z∣−127≤x≤127},Z32={x∈Z∣−231≤x≤231−1}\mathbb{Z}_4 = \{ x \in \mathbb{Z} \mid -8 \le x \le 7 \}, \quad \mathbb{Z}_8^{\text{sym}} = \{ x \in \mathbb{Z} \mid -127 \le x \le 127 \}, \quad \mathbb{Z}_{32} = \{ x \in \mathbb{Z} \mid -2^{31} \le x \le 2^{31}-1 \}。其中 Z8sym\mathbb{Z}_8^{\text{sym}} 的上标 sym\text{sym} 表示对称量化值域区间:其值域关于 −127-127 与 127127 对称取整,与标准 INT8 的 [−128,127][-128, 127] 值域不同,故以 sym\text{sym} 上标区分。
- 张量切片操作采用Python风格的
start:stop:step表示法,例如[0::2,:][0::2, :] 代表取偶数行、[1::2,:][1::2, :] 代表取奇数行。 - bitcastT(Z)\mathrm{bitcast}_{T}(\mathbf{Z}) 表示二进制重解释操作,将张量Z\mathbf{Z}的底层二进制数据按目标类型 TT 重新解释。
-
激活函数公式:
- 记 Linear1 输出拆分后的 gate 分支为 G\mathbf{G},up 分支为 U\mathbf{U},激活输出为 A\mathbf{A}。下文将由
activation和activation_params共同确定的具体激活计算统称为 Activation。Sigmoid 函数和 SiLU 函数定义为:σ(z)=11+e−z,SiLU(z)=z⋅σ(z)=z1+e−z.\sigma(z)=\frac{1}{1+e^{-z}}, \qquad \operatorname{SiLU}(z)=z\cdot\sigma(z)=\frac{z}{1+e^{-z}}.
记截断值为 cc;未启用截断(未配置或配置为 00)时,数学上取 c=+∞c=+\infty。定义 Gc=min(G,c)\mathbf{G}_c=\min(\mathbf{G},c),Uc=clip(U,−c,c)\mathbf{U}_c=\operatorname{clip}(\mathbf{U},-c,c)。 swiglu:A=SwiGLU(G,U)=Swish1(Gc)⊙Uc=SiLU(Gc)⊙Uc.\mathbf{A}=\operatorname{SwiGLU}(\mathbf{G},\mathbf{U}) =\operatorname{Swish}_1(\mathbf{G}_c)\odot\mathbf{U}_c =\operatorname{SiLU}(\mathbf{G}_c)\odot\mathbf{U}_c.
swiglustep:A=SwiGLUStep(G,U)=min (SiLU(G),c)⊙Uc.\mathbf{A}=\operatorname{SwiGLUStep}(\mathbf{G},\mathbf{U})=\min\!\left(\operatorname{SiLU}(\mathbf{G}),c\right)\odot\mathbf{U}_c.
swigluoai:A=SwiGLUOAI(G,U)=Gc⊙σ(αGc)⊙(Uc+β).\mathbf{A}=\operatorname{SwiGLUOAI}(\mathbf{G},\mathbf{U})=\mathbf{G}_c\odot\sigma(\alpha\mathbf{G}_c)\odot(\mathbf{U}_c+\beta).
situglu:A=SiTUGLU(G,U)=βtanh (Gβ)⊙σ(G)⊙L(U;βlinear),\mathbf{A}=\operatorname{SiTUGLU}(\mathbf{G},\mathbf{U})=\beta\tanh\!\left(\frac{\mathbf{G}}{\beta}\right)\odot\sigma(\mathbf{G})\odot L(\mathbf{U};\beta_{\mathrm{linear}}),
其中L(U;βlinear)={U,未配置 linear_beta,βlineartanh (Uβlinear),已配置 linear_beta.L(\mathbf{U};\beta_{\mathrm{linear}})= \begin{cases} \mathbf{U}, & \text{未配置 linear\_beta},\\ \beta_{\mathrm{linear}}\tanh\!\left(\dfrac{\mathbf{U}}{\beta_{\mathrm{linear}}}\right), & \text{已配置 linear\_beta}. \end{cases}
- 记 Linear1 输出拆分后的 gate 分支为 G\mathbf{G},up 分支为 U\mathbf{U},激活输出为 A\mathbf{A}。下文将由
-
-
计算过程
各产品支持的Linear计算时的激活矩阵A和权重矩阵W的数据类型如下:
场景名 A W A16W16 BFLOAT16 BFLOAT16 A8W8-INT INT8 INT8 A8W8-FP FLOAT8_E4M3FN、FLOAT8_E5M2 FLOAT8_E4M3FN、FLOAT8_E5M2 A8W4-INT INT8 INT4 A8W4-FP FLOAT8_E4M3FN FLOAT4_E2M1 A4W4-FP FLOAT4_E2M1 FLOAT4_E2M1 - Atlas A2系列产品、Atlas A3系列产品:不支持上表中A8W8-FP场景。
- Ascend 950PR&950DT系列产品:不支持上表中A16W16、A8W8-INT、A8W4-INT场景。
- Ascend 950PR&950DT系列产品的dispatch阶段有两条路径:
dispatchQuantMode= 4时,按下文各量化场景的描述由算子内部对BF16的x做MX逐组量化;dispatchQuantMode= 0时为预量化直通,x已经是量化后的数据、缩放因子由scales入参给出,算子跳过下文第一阶段的量化步骤,直接用x与scales参与后续矩阵乘,其余阶段与下文一致。 - Ascend 950PR&950DT系列产品:MoE专家与共享专家可以采用不同的权重类型与量化类型,共享专家的量化输出类型由
sharedExpertQuantOutDtype指定,未显式配置时与dispatchQuantOutDtype一致。
A16W16 非量化场景
-
EP Dispatch
在 Dispatch 阶段,每个 tokeni\text{token}_i 将其token表示 xi\mathbf{x}_i 发送给专家 ei,0,ei,1,…,ei,topK−1e_{i,0}, e_{i,1}, \dots, e_{i,\text{topK}-1}。即对于每个 kk,专家 ei,ke_{i,k} 接收一份 xi\mathbf{x}_i。
记 Ie={ i∣∃k, E[i,k]=e }I_e = \{\, i \mid \exists k,\ \mathbf{E}[i,k]=e \,\} 为所有被分派给专家 ee 的 token 索引集合,集合 IeI_e 的大小 Ne=∣Ie∣N_e = |I_e| 即为专家 ee 需要处理的 token 总数,则有 Xe∈RNe×hidden\mathbf{X}_e \in \mathbb{R}^{N_e \times \text{hidden}} 是由所有满足 i∈Iei \in I_e 的token表示 xi\mathbf{x}_i 按任意固定顺序行堆叠而成的矩阵,该矩阵即为专家 ee 经过 Dispatch 后收到的全部 token 表示。
对于每个 tokeni\text{token}_i 及其选中的第 kk 个专家 ei,ke_{i,k},存在唯一的行索引 row(i,k)∈{0,…,Nei,k−1}\operatorname{row}(i,k) \in \{0,\dots,N_{e_{i,k}}-1\},使得 Xei,k[row(i,k),:]=xi\mathbf{X}_{e_{i,k}}[\operatorname{row}(i,k), :] = \mathbf{x}_i。该映射记录了 xi\mathbf{x}_i 在专家 ei,ke_{i,k} 的输入矩阵 Xei,k\mathbf{X}_{e_{i,k}} 中的位置。
-
Expert Compute
在 MoE 层中,每个专家本质上是一个独立的前馈网络(FFN),采用由
activation指定的门控激活结构以提升表达能力。整个计算过程分为如下三个子步骤。1. Linear1 投影
Linear1 投影是专家网络的第一层线性变换,同时产生 gate 部分 和 up 部分 所需的预激活值。其计算公式为
He=Xe⋅W1[e](∈RNe×2⋅intermediateHidden)\mathbf{H}_e = \mathbf{X}_e \cdot \mathbf{W}_1[e] \quad\bigl(\in \mathbb{R}^{N_e \times 2\cdot\text{intermediateHidden}}\bigr)
2. 激活
将 He\mathbf{H}_e 沿列维度拆分为 gate 分支 Ge\mathbf{G}_e 和 up 分支 Ue\mathbf{U}_e,根据
activation计算中间激活表示 Ae\mathbf{A}_e;各可选激活类型的计算方式参见激活函数公式。3. Linear2 投影
Linear2 投影作为第二层线性变换,将中间激活表示 Ae\mathbf{A}_e 从高维空间投影回原始的隐藏维度 hidden\text{hidden},使专家输出能够与残差连接等后续操作兼容。
Ye=Ae⋅W2[e](∈RNe×hidden)\mathbf{Y}_e = \mathbf{A}_e \cdot \mathbf{W}_2[e] \quad\bigl(\in \mathbb{R}^{N_e \times \text{hidden}}\bigr)
经过以上计算,专家 ee 的每一行输出对应其批次中的一个 token。对于 tokeni\text{token}_i,它在专家 ei,ke_{i,k} 中的输出行即为 Yei,k[row(i,k), :]\mathbf{Y}_{e_{i,k}}\bigl[\operatorname{row}(i,k),\,:\bigr]。
-
Token Combine
Combine 负责收集所有专家计算出的输出向量,按照每个 token 原先分配到的专家权重进行加权求和,最终为每个 token 生成一个融合后的输出。利用之前记录的位置索引 row(i,k)\operatorname{row}(i,k),从专家 ei,ke_{i,k} 的输出矩阵中收回属于 tokeni\text{token}_i 的行,并与门控权重相乘后求和:
yi=∑k=0topK−1wk ⋅ Yei,k [ row(i,k), : ](∈R1×hidden)\mathbf{y}_i = \sum_{k=0}^{\text{topK} - 1} w_k \;\cdot\; \mathbf{Y}_{e_{i,k}}\!\bigl[\,\operatorname{row}(i,k),\,:\,\bigr] \qquad\bigl(\in \mathbb{R}^{1 \times \text{hidden}}\bigr)
其中 wk=G[i,k]w_k = \mathbf{G}[i,k] 为 tokeni\text{token}_i 对专家 ei,ke_{i,k} 的门控权重。
所有 token 的输出按输入顺序堆叠为最终输出 Y∈RtotalNumTokens×hidden\mathbf{Y} \in \mathbb{R}^{\text{totalNumTokens} \times \text{hidden}}。
A8W8-INT 量化场景
-
输入
- SW1∈RmoeExpertNum×(2×intermediateHidden)\mathbf{S}^{W1} \in \mathbb{R}^{\text{moeExpertNum} \times (2\times \text{intermediateHidden})}:Linear1 权重矩阵的逐通道缩放因子,对应入参
weightScales1。 - SW2∈RmoeExpertNum×hidden\mathbf{S}^{W2} \in \mathbb{R}^{\text{moeExpertNum} \times \text{hidden}}:Linear2 权重矩阵的逐通道缩放因子,对应入参
weightScales2。
- SW1∈RmoeExpertNum×(2×intermediateHidden)\mathbf{S}^{W1} \in \mathbb{R}^{\text{moeExpertNum} \times (2\times \text{intermediateHidden})}:Linear1 权重矩阵的逐通道缩放因子,对应入参
-
EP Dispatch
在 Dispatch 通信之前,首先将原始 BF16 激活矩阵 X\mathbf{X} 量化为 INT8。对每个 tokeni\text{token}_i,计算其逐 token 缩放因子:
siX=max(∣X[i,:]∣)127∈Rs^{X}_i = \frac{\max(|\mathbf{X}[i,:]|)}{127} \in \mathbb{R}
然后量化得到 INT8 表示:
qi=⌊X[i,:]siX⌉∈(Z8sym)1×hidden\mathbf{q}_i = \left\lfloor \frac{\mathbf{X}[i,:]}{s^{X}_i} \right\rceil \quad \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{1 \times \text{hidden}}
在 Dispatch 通信阶段,每个 tokeni\text{token}_i 将其量化后的向量 qi\mathbf{q}_i 和缩放因子 siXs^{X}_i 发送给专家 ei,0,ei,1,…,ei,topK−1e_{i,0}, e_{i,1}, \dots, e_{i,\text{topK}-1}(ei,k=E[i,k]e_{i,k} = \mathbf{E}[i,k])。
记 Ie={ i∣∃k, E[i,k]=e }I_e = \{\, i \mid \exists k,\ \mathbf{E}[i,k]=e \,\} 为所有被分派给专家 ee 的 token 索引集合,集合 IeI_e 的大小 Ne=∣Ie∣N_e = |I_e| 即为专家 ee 需要处理的 token 总数。则有 Qe∈(Z8sym)Ne×hidden\mathbf{Q}_e \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{N_e \times \text{hidden}} 是由所有满足 i∈Iei \in I_e 的 qi\mathbf{q}_i 按任意固定顺序行堆叠而成的矩阵,该矩阵即为专家 ee 经过 Dispatch 后收到的全部 token 表示;同理,对应的专家 ee 收到的缩放因子向量记为 seX∈RNe\mathbf{s}^{X}_e \in \mathbb{R}^{N_e},其元素由所有满足 i∈Iei \in I_e 的 siXs^{X}_i 按与 Qe\mathbf{Q}_e 相同的行顺序堆叠而成。
对于每个 tokeni\text{token}_i 及其选中的第 kk 个专家 ei,ke_{i,k},存在唯一的行索引 row(i,k)∈{0,…,Nei,k−1}\operatorname{row}(i,k) \in \{0,\dots,N_{e_{i,k}}-1\},使得 Qei,k[row(i,k),:]=qi\mathbf{Q}_{e_{i,k}}[\operatorname{row}(i,k), :] = \mathbf{q}_i。该映射记录了 qi\mathbf{q}_i 在专家 ei,ke_{i,k} 的输入矩阵中的位置。
-
Expert Compute
在 MoE 层中,每个专家本质上是一个独立的前馈网络(FFN),采用由
activation指定的门控激活结构以提升表达能力。在A8W8场景下,两个线性层都使用 INT8 输入和 INT8 权重进行矩阵乘,得到 INT32 中间结果并反量化。具体分为三个子步骤。1. Linear1 投影(INT8 矩阵乘 + 反量化)
Linear1 投影是专家网络的第一层线性变换,同时产生 gate 部分 和 up 部分 所需的预激活值。计算时执行 INT8 矩阵乘法,得到 INT32 计算结果:
Ceint32=Qe⋅W1[e]int8∈Z32Ne×2⋅intermediateHidden\mathbf{C}_e^{\text{int32}} = \mathbf{Q}_e \cdot \mathbf{W}_1[e]^{\text{int8}} \quad \in \mathbb{Z}_{32}^{N_e \times 2\cdot\text{intermediateHidden}}
然后反量化为预激活值 He\mathbf{H}_e:
He=(Ceint32⊙seW1)⊙seX∈RNe×2⋅intermediateHidden\mathbf{H}_e = \left( \mathbf{C}_e^{\text{int32}} \odot \mathbf{s}^{W1}_e \right) \odot \mathbf{s}^{X}_e \quad \in \mathbb{R}^{N_e \times 2\cdot\text{intermediateHidden}}
2. 激活
将 He\mathbf{H}_e 沿列维度拆分为 gate 分支 Ge\mathbf{G}_e 和 up 分支 Ue\mathbf{U}_e,根据
activation计算中间激活表示 Ae\mathbf{A}_e;各可选激活类型的计算方式参见激活函数公式。3. Linear2 投影(量化 + INT8 矩阵乘 + 反量化)
Linear2 投影作为第二层线性变换,将中间激活表示 Ae\mathbf{A}_e 从高维空间投影回原始的隐藏维度 hidden\text{hidden},使专家输出能够与残差连接等后续操作兼容。 在 A8W8 场景下,需要将激活值量化为 INT8,因此先对 Ae\mathbf{A}_e 的每一行(每个 token)计算缩放因子:
siAe=max(∣Ae[i,:]∣)127,i=0,…,Ne−1s^{A_e}_i = \frac{\max(|\mathbf{A}_e[i,:]|)}{127}, \quad i=0,\dots,N_e-1
得到专家 ee 在 Linear2 计算时的激活缩放因子 seAe∈RNe\mathbf{s}^{A_e}_e \in \mathbb{R}^{N_e}。然后量化:
Aeint8[i,:]=⌊Ae[i,:]siAe⌉∈(Z8sym)Ne×intermediateHidden\mathbf{A}_e^{\text{int8}}[i,:] = \left\lfloor \frac{\mathbf{A}_e[i,:]}{s^{A_e}_i} \right\rceil \quad \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{N_e \times \text{intermediateHidden}}
再执行 INT8 矩阵乘法并反量化:
Deint32=Aeint8⋅W2[e]int8∈Z32Ne×hidden\mathbf{D}_e^{\text{int32}} = \mathbf{A}_e^{\text{int8}} \cdot \mathbf{W}_2[e]^{\text{int8}} \quad \in \mathbb{Z}_{32}^{N_e \times \text{hidden}}
Ye=(Deint32⊙seW2)⊙seAe∈RNe×hidden\mathbf{Y}_e = \left( \mathbf{D}_e^{\text{int32}} \odot \mathbf{s}^{W2}_e \right) \odot \mathbf{s}^{A_e}_e \quad \in \mathbb{R}^{N_e \times \text{hidden}}
经过以上计算,专家 ee 的每一行输出对应其批次中的一个 token。对于 tokeni\text{token}_i,它在专家 ei,ke_{i,k} 中的输出行即为 Yei,k[row(i,k), :]\mathbf{Y}_{e_{i,k}}\bigl[\operatorname{row}(i,k),\,:\bigr]。
-
Token Combine
Combine 负责收集所有专家计算出的输出向量,按照每个 token 原先分配到的专家权重进行加权求和,最终为每个 token 生成一个融合后的输出。利用之前记录的位置索引 row(i,k)\operatorname{row}(i,k),从专家 ei,ke_{i,k} 的输出矩阵中收回属于 tokeni\text{token}_i 的行,并与门控权重相乘后求和:
yi=∑k=0topK−1wk ⋅ Yei,k [ row(i,k), : ]∈R1×hidden\mathbf{y}_i = \sum_{k=0}^{\text{topK} - 1} w_k \;\cdot\; \mathbf{Y}_{e_{i,k}}\!\bigl[\,\operatorname{row}(i,k),\,:\,\bigr] \quad \in \mathbb{R}^{1 \times \text{hidden}}
其中 wk=G[i,k]w_k = \mathbf{G}[i,k] 为 tokeni\text{token}_i 对专家 ei,ke_{i,k} 的门控权重。
所有 token 的输出按输入顺序堆叠为最终输出 Y∈RtotalNumTokens×hidden\mathbf{Y} \in \mathbb{R}^{\text{totalNumTokens} \times \text{hidden}}。
A8W4-INT 量化场景
-
输入
- SW1∈RmoeExpertNum×(2×intermediateHidden)\mathbf{S}^{W1} \in \mathbb{R}^{\text{moeExpertNum} \times (2\times \text{intermediateHidden})}:Linear1 权重矩阵的逐通道缩放因子,对应入参
weightScales1。 - SW2∈RmoeExpertNum×hidden\mathbf{S}^{W2} \in \mathbb{R}^{\text{moeExpertNum} \times \text{hidden}}:Linear2 权重矩阵的逐通道缩放因子,对应入参
weightScales2。 - B1∈RmoeExpertNum×(2×intermediateHidden)\mathbf{B}_1 \in \mathbb{R}^{\text{moeExpertNum} \times (2\times \text{intermediateHidden})}:Linear1 的偏置矩阵,由 INT4 量化过程离线生成,对应入参
bias1。 - B2∈RmoeExpertNum×hidden\mathbf{B}_2 \in \mathbb{R}^{\text{moeExpertNum} \times \text{hidden}}:Linear2 的偏置矩阵,由 INT4 量化过程离线生成,对应入参
bias2。
- SW1∈RmoeExpertNum×(2×intermediateHidden)\mathbf{S}^{W1} \in \mathbb{R}^{\text{moeExpertNum} \times (2\times \text{intermediateHidden})}:Linear1 权重矩阵的逐通道缩放因子,对应入参
-
EP Dispatch
在 Dispatch 通信之前,首先将原始 BF16 激活矩阵 X\mathbf{X} 量化为 INT8。对每个 tokeni\text{token}_i,计算其逐 token 缩放因子:
siX=max(∣X[i,:]∣)127∈Rs^{X}_i = \frac{\max(|\mathbf{X}[i,:]|)}{127} \in \mathbb{R}
然后量化得到 INT8 表示:
qi=⌊X[i,:]siX⌉∈(Z8sym)1×hidden\mathbf{q}_i = \left\lfloor \frac{\mathbf{X}[i,:]}{s^{X}_i} \right\rceil \quad \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{1 \times \text{hidden}}
在 Dispatch 通信阶段,每个 tokeni\text{token}_i 将其量化后的向量 qi\mathbf{q}_i 和缩放因子 siXs^{X}_i 发送给专家 ei,0,ei,1,…,ei,topK−1e_{i,0}, e_{i,1}, \dots, e_{i,\text{topK}-1}
记 Ie={ i∣∃k, E[i,k]=e }I_e = \{\, i \mid \exists k,\ \mathbf{E}[i,k]=e \,\} 为所有被分派给专家 ee 的 token 索引集合,集合 IeI_e 的大小 Ne=∣Ie∣N_e = |I_e| 即为专家 ee 需要处理的 token 总数。则有 Qe∈(Z8sym)Ne×hidden\mathbf{Q}_e \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{N_e \times \text{hidden}} 是由所有满足 i∈Iei \in I_e 的 qi\mathbf{q}_i 按任意固定顺序行堆叠而成的矩阵,该矩阵即为专家 ee 经过 Dispatch 后收到的全部 token 表示;同理,对应的专家 ee 收到的缩放因子向量记为 seX∈RNe\mathbf{s}^{X}_e \in \mathbb{R}^{N_e},其元素由所有满足 i∈Iei \in I_e 的 siXs^{X}_i 按与 Qe\mathbf{Q}_e 相同的行顺序堆叠而成。
对于每个 tokeni\text{token}_i 及其选中的第 kk 个专家 ei,ke_{i,k},存在唯一的行索引 row(i,k)∈{0,…,Nei,k−1}\operatorname{row}(i,k) \in \{0,\dots,N_{e_{i,k}}-1\},使得 Qei,k[row(i,k),:]=qi\mathbf{Q}_{e_{i,k}}[\operatorname{row}(i,k), :] = \mathbf{q}_i。该映射记录了 qi\mathbf{q}_i 在专家 ei,ke_{i,k} 的输入矩阵中的位置。
-
Expert Compute
在 MoE 层中,每个专家本质上是一个独立的前馈网络(FFN),采用由
activation指定的门控激活结构以提升表达能力。在A8W4-INT场景下,两个线性层都采用MSD(Mixed-precision Split-activation Decomposition,混合精度激活拆分分解)方案进行矩阵乘,通过将 INT8 值拆为高4位和低4位两个有符号 INT4,使得 INT8×INT4 的矩阵乘可分解为两个 INT4×INT4 的矩阵乘,从而利用硬件的 INT4 矩阵乘加速。该方案的数学原理和实现逻辑可参阅GroupedMatmul W4A8量化与MSD方案。1. 生成精度补偿的偏置矩阵(离线生成,在算子外完成,并作为算子输入)
MSD 方案的核心是将量化后的 INT8 激活值二进制重解释地拆分为两个 INT4 分量。由于低位 INT4 分量按 (Xint8&0x0F)−8(\mathbf{X}^{\text{int8}} \mathbin{\&} 0x0F) - 8 定义,其数值范围被映射到 [−8,7][-8, 7],这相当于在原始无符号低 4 位(0~15)的基础上减去了 8。当将高、低位的 INT4 分别与权重矩阵做矩阵乘并合并时,该偏移会引入一个常数项,需要在最终结果中予以补偿。
记原始 INT8 激活矩阵为 Xint8\mathbf{X}^{\text{int8}},拆分后的高位和低位 INT4 激活矩阵分别为 X1int4\mathbf{X}_1^{\text{int4}} 和 X2int4\mathbf{X}_2^{\text{int4}},权重矩阵为 W\mathbf{W}。恢复关系为:
Xint8=16×X1int4+(X2int4+8⋅1mat)\mathbf{X}^{\text{int8}} = 16 \times \mathbf{X}_1^{\text{int4}} + (\mathbf{X}_2^{\text{int4}} + 8 \cdot \mathbf{1}_{\text{mat}})
其中 1mat\mathbf{1}_{\text{mat}} 为与 X2int4\mathbf{X}_2^{\text{int4}} 形状相同的全 1 矩阵,用于逐元素加 8。令 1\mathbf{1} 为形状与输入特征维度一致的全 1 列向量,则矩阵乘展开为:
Xint8⋅W=16⋅(X1int4⋅W)+(X2int4⋅W)+8⋅(1⊤⋅W)\mathbf{X}^{\text{int8}} \cdot \mathbf{W} = 16 \cdot (\mathbf{X}_1^{\text{int4}} \cdot \mathbf{W}) + (\mathbf{X}_2^{\text{int4}} \cdot \mathbf{W}) + 8 \cdot (\mathbf{1}^\top \cdot \mathbf{W})
这里 1⊤⋅W\mathbf{1}^\top \cdot \mathbf{W} 表示对权重矩阵 W\mathbf{W} 的每一列求和,其结果为一个行向量(形状与输出维度相同)。在具体实现中,该行向量会被广播到批次维度,加到所有 token 的输出上。可见,若只计算前两项,会缺失一个正数项。为了精确恢复结果,需预先计算补偿偏置:
bias=8⋅(1⊤⋅W),\text{bias} = 8 \cdot (\mathbf{1}^\top \cdot \mathbf{W}),
B1\mathbf{B}_1 和 B2\mathbf{B}_2 均按此法,分别使用对应的全 1 列向量(维度分别为 hidden\text{hidden} 和 intermediateHidden\text{intermediateHidden})与各自的权重矩阵相乘,得到形状匹配的偏置行向量。这些偏置在离线阶段计算完成后传入算子,在合并高低位结果时直接参与加法,从而消除偏移引入的误差。
2. Linear1 投影(INT4 × INT4 矩阵乘 + 反量化)
Linear1 投影是专家网络的第一层线性变换,同时产生 gate 部分 和 up 部分 所需的预激活值。
(1) 激活重解释为INT4
将 INT8 激活张量 Qeint8∈(Z8sym)Ne×hidden\mathbf{Q}_e^{\text{int8}} \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{N_e \times \text{hidden}} 二进制重解释为两个 INT4 交替拼接的视图:
Qeint4=bitcastZ42Ne×hidden(Qeint8)∈Z42Ne×hidden\mathbf{Q}_e^{\text{int4}} = \mathrm{bitcast}_{\mathbb{Z}_4^{2N_e \times \text{hidden}}} \left( \mathbf{Q}_e^{\text{int8}} \right) \in \mathbb{Z}_4^{2N_e \times \text{hidden}}
其中高位和低位分量直接由 Qeint4\mathbf{Q}_e^{\text{int4}} 的偶数行和奇数行给出:
Qehigh=Qeint4[0::2,:]∈Z4Ne×hidden,Qelow=Qeint4[1::2,:]∈Z4Ne×hidden\mathbf{Q}_e^{\text{high}} = \mathbf{Q}_e^{\text{int4}}[0::2, :] \in \mathbb{Z}_4^{N_e \times \text{hidden}}, \quad \mathbf{Q}_e^{\text{low}} = \mathbf{Q}_e^{\text{int4}}[1::2, :] \in \mathbb{Z}_4^{N_e \times \text{hidden}}
它们在数值上可以由原 INT8 经如下计算得到:
Qehigh=⌊Qeint816⌋,Qelow=(Qeint8&0x0F)−8\mathbf{Q}_e^{\text{high}} = \left\lfloor \frac{\mathbf{Q}_e^{\text{int8}}}{16} \right\rfloor, \quad \mathbf{Q}_e^{\text{low}} = (\mathbf{Q}_e^{\text{int8}} \mathbin{\&} 0x0F) - 8
恢复关系为 Qeint8=16Qehigh+(Qelow+8)\mathbf{Q}_e^{\text{int8}} = 16\mathbf{Q}_e^{\text{high}} + (\mathbf{Q}_e^{\text{low}} + 8)。由于 bitcast\mathrm{bitcast} 仅改变类型视图,Qeint4\mathbf{Q}_e^{\text{int4}} 与 Qeint8\mathbf{Q}_e^{\text{int8}} 共享底层物理内存,无需任何数据重排或拷贝。
(2) INT4 × INT4 矩阵乘与权重反量化
将重解释后的 INT4 激活视图 Qeint4∈Z42Ne×hidden\mathbf{Q}_e^{\text{int4}} \in \mathbb{Z}_4^{2N_e \times \text{hidden}} 与权重矩阵 W1[e]∈Rhidden×2⋅intermediateHidden\mathbf{W}_1[e] \in \mathbb{R}^{\text{hidden} \times 2\cdot\text{intermediateHidden}} 执行矩阵乘,并应用权重缩放因子 seW1\mathbf{s}^{W1}_e 进行反量化,得到结果:
Ce=(Qeint4⋅W1[e])⊙seW1 ∈ R2Ne×2⋅intermediateHidden\mathbf{C}_e = \bigl( \mathbf{Q}_e^{\text{int4}} \cdot \mathbf{W}_1[e] \bigr) \odot \mathbf{s}^{W1}_e \;\in\; \mathbb{R}^{2N_e \times 2\cdot\text{intermediateHidden}}
将结果按偶数行和奇数行分别记为如下的矩阵视图,它们即对应于Qehigh\mathbf{Q}_e^{\text{high}}和Qelow\mathbf{Q}_e^{\text{low}}的计算结果:
Cehigh=Ce[0::2,:]∈RNe×2⋅intermediateHidden,Celow=Ce[1::2,:]∈RNe×2⋅intermediateHidden\mathbf{C}_e^{\text{high}} = \mathbf{C}_e[0::2, :] \in \mathbb{R}^{N_e \times 2\cdot\text{intermediateHidden}}, \qquad \mathbf{C}_e^{\text{low}} = \mathbf{C}_e[1::2, :] \in \mathbb{R}^{N_e \times 2\cdot\text{intermediateHidden}}
(3) 精度补偿与激活反量化
利用偏置 B1[e]\mathbf{B}_1[e] 和激活缩放因子 seX\mathbf{s}^{X}_e(行向量)分别进行精度补偿和激活反量化,最终预激活值为:
He=(16⋅Cehigh+Celow+B1[e])⊙seX∈RNe×2⋅intermediateHidden\mathbf{H}_e = \Bigl( 16 \cdot \mathbf{C}_e^{\text{high}} + \mathbf{C}_e^{\text{low}} + \mathbf{B}_1[e] \Bigr) \odot \mathbf{s}^{X}_e \quad\in \mathbb{R}^{N_e \times 2\cdot\text{intermediateHidden}}
其中 ⊙seX\odot \mathbf{s}^{X}_e 表示将矩阵的每一行乘以 seX\mathbf{s}^{X}_e 中对应的标量。
3. 激活
将 He\mathbf{H}_e 沿列维度拆分为 gate 分支 Ge\mathbf{G}_e 和 up 分支 Ue\mathbf{U}_e,根据
activation计算中间激活表示 Ae\mathbf{A}_e;各可选激活类型的计算方式参见激活函数公式。4. Linear2 投影(量化 + INT4 × INT4 矩阵乘 + 反量化)
Linear2 投影作为第二层线性变换,将中间激活表示 Ae\mathbf{A}_e 从高维空间投影回原始的隐藏维度 hidden\text{hidden},使专家输出能够与残差连接等后续操作兼容。 在 A8W4 场景下,首先将激活值量化为 INT8,再通过二进制重解释为两个 INT4 的拼接视图,以一次矩阵乘完成计算,过程如下。
(1) 激活量化
对 Ae\mathbf{A}_e 的每一行计算缩放因子并量化至 INT8:
siAe=max(∣Ae[i,:]∣)127,i=0,…,Ne−1s^{A_e}_i = \frac{\max(|\mathbf{A}_e[i,:]|)}{127}, \quad i=0,\dots,N_e-1
得到专家 ee 在 Linear2 计算时的激活缩放因子 seAe∈RNe\mathbf{s}^{A_e}_e \in \mathbb{R}^{N_e},并计算量化结果:
Aeint8[i,:]=⌊Ae[i,:]siAe⌉∈(Z8sym)Ne×intermediateHidden\mathbf{A}_e^{\text{int8}}[i,:] = \left\lfloor \frac{\mathbf{A}_e[i,:]}{s^{A_e}_i} \right\rceil \quad \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{N_e \times \text{intermediateHidden}}
(2) 激活重解释为 INT4
将 INT8 激活张量 Aeint8∈(Z8sym)Ne×intermediateHidden\mathbf{A}_e^{\text{int8}} \in \left(\mathbb{Z}_8^{\text{sym}}\right)^{N_e \times \text{intermediateHidden}} 二进制重解释为两个 INT4 交替拼接的视图:
Aeint4=bitcastZ42Ne×intermediateHidden(Aeint8)∈Z42Ne×intermediateHidden\mathbf{A}_e^{\text{int4}} = \mathrm{bitcast}_{\mathbb{Z}_4^{2N_e \times \text{intermediateHidden}}} \left( \mathbf{A}_e^{\text{int8}} \right) \in \mathbb{Z}_4^{2N_e \times \text{intermediateHidden}}
其中高位和低位分量直接由 Aeint4\mathbf{A}_e^{\text{int4}} 的偶数行和奇数行给出:
Aehigh=Aeint4[0::2,:]∈Z4Ne×intermediateHidden,Aelow=Aeint4[1::2,:]∈Z4Ne×intermediateHidden\mathbf{A}_e^{\text{high}} = \mathbf{A}_e^{\text{int4}}[0::2, :] \in \mathbb{Z}_4^{N_e \times \text{intermediateHidden}}, \quad \mathbf{A}_e^{\text{low}} = \mathbf{A}_e^{\text{int4}}[1::2, :] \in \mathbb{Z}_4^{N_e \times \text{intermediateHidden}}
它们在数值上可以由原 INT8 经如下计算得到:
Aehigh=⌊Aeint816⌋,Aelow=(Aeint8&0x0F)−8\mathbf{A}_e^{\text{high}} = \left\lfloor \frac{\mathbf{A}_e^{\text{int8}}}{16} \right\rfloor, \quad \mathbf{A}_e^{\text{low}} = (\mathbf{A}_e^{\text{int8}} \mathbin{\&} 0x0F) - 8
恢复关系为 Aeint8=16Aehigh+(Aelow+8)\mathbf{A}_e^{\text{int8}} = 16\mathbf{A}_e^{\text{high}} + (\mathbf{A}_e^{\text{low}} + 8)。由于 bitcast\mathrm{bitcast} 仅改变类型视图,Aeint4\mathbf{A}_e^{\text{int4}} 与 Aeint8\mathbf{A}_e^{\text{int8}} 共享底层物理内存,无需任何数据重排或拷贝。
(3) INT4 × INT4 矩阵乘与权重反量化
将重解释后的 INT4 激活视图 Aeint4∈Z42Ne×intermediateHidden\mathbf{A}_e^{\text{int4}} \in \mathbb{Z}_4^{2N_e \times \text{intermediateHidden}} 与权重矩阵 W2[e]∈RintermediateHidden×hidden\mathbf{W}_2[e] \in \mathbb{R}^{\text{intermediateHidden} \times \text{hidden}} 执行矩阵乘,并应用权重缩放因子 seW2\mathbf{s}^{W2}_e 进行反量化,得到结果:
De=(Aeint4⋅W2[e])⊙seW2 ∈ R2Ne×hidden\mathbf{D}_e = \bigl( \mathbf{A}_e^{\text{int4}} \cdot \mathbf{W}_2[e] \bigr) \odot \mathbf{s}^{W2}_e \;\in\; \mathbb{R}^{2N_e \times \text{hidden}}
将结果按偶数行和奇数行分别记为如下的矩阵视图,它们即对应于 Aehigh\mathbf{A}_e^{\text{high}} 和 Aelow\mathbf{A}_e^{\text{low}} 的计算结果:
Dehigh=De[0::2,:]∈RNe×hidden,Delow=De[1::2,:]∈RNe×hidden\mathbf{D}_e^{\text{high}} = \mathbf{D}_e[0::2, :] \in \mathbb{R}^{N_e \times \text{hidden}}, \qquad \mathbf{D}_e^{\text{low}} = \mathbf{D}_e[1::2, :] \in \mathbb{R}^{N_e \times \text{hidden}}
(4) 精度补偿与激活反量化
利用偏置 B2[e]\mathbf{B}_2[e] 和激活缩放因子 seAe\mathbf{s}^{A_e}_e(行向量)分别进行精度补偿和激活反量化,最终输出为:
Ye=(16⋅Dehigh+Delow+B2[e])⊙seAe∈RNe×hidden\mathbf{Y}_e = \Bigl( 16 \cdot \mathbf{D}_e^{\text{high}} + \mathbf{D}_e^{\text{low}} + \mathbf{B}_2[e] \Bigr) \odot \mathbf{s}^{A_e}_e \quad\in \mathbb{R}^{N_e \times \text{hidden}}
其中 ⊙seAe\odot \mathbf{s}^{A_e}_e 表示将矩阵的每一行乘以 seAe\mathbf{s}^{A_e}_e 中对应的标量。
经过以上计算,专家 ee 的每一行输出对应其批次中的一个 token。对于 tokeni\text{token}_i,它在专家 ei,ke_{i,k} 中的输出行即为 Yei,k[row(i,k), :]\mathbf{Y}_{e_{i,k}}\bigl[\operatorname{row}(i,k),\,:\bigr]。
-
Token Combine
Combine 负责收集所有专家计算出的输出向量,按照每个 token 原先分配到的专家权重进行加权求和,最终为每个 token 生成一个融合后的输出。利用之前记录的位置索引 row(i,k)\operatorname{row}(i,k),从专家 ei,ke_{i,k} 的输出矩阵中收回属于 tokeni\text{token}_i 的行,并与门控权重相乘后求和:
yi=∑k=0topK−1wk ⋅ Yei,k [ row(i,k), : ](∈R1×hidden)\mathbf{y}_i = \sum_{k=0}^{\text{topK} - 1} w_k \;\cdot\; \mathbf{Y}_{e_{i,k}}\!\bigl[\,\operatorname{row}(i,k),\,:\,\bigr] \qquad\bigl(\in \mathbb{R}^{1 \times \text{hidden}}\bigr)
其中 wk=G[i,k]w_k = \mathbf{G}[i,k] 为 tokeni\text{token}_i 对专家 ei,ke_{i,k} 的门控权重。
所有 token 的输出按输入顺序堆叠为最终输出 Y∈RtotalNumTokens×hidden\mathbf{Y} \in \mathbb{R}^{\text{totalNumTokens} \times \text{hidden}}。
A8W8-FP 量化场景
第一阶段对输入 Token 按专家分组收集后做 MXFP8 量化,生成各专家的量化输入与缩放因子:
X^e, SX,e=QMX (X[Te]),e=0,1,…,Elocal−1\hat{X}_e,\ S_{X,e} = \mathrm{Q}_{\text{MX}}\!\left(X[\mathcal{T}_e]\right), \quad e = 0, 1, \ldots, E_{\text{local}}-1
说明:根据
topkIds将 Token 按专家排序收集,Te\mathcal{T}_e 为分配到专家 ee 的 Token 索引集合,ElocalE_{\text{local}} 表示本 Rank 的路由 MoE 专家数。X[Te]X[\mathcal{T}_e] 为专家 ee 对应的输入子矩阵,其行数由该专家本次实际接收的 Token 数决定。QMX\mathrm{Q}_{\text{MX}} 表示 MX 逐组量化(group size = 32),对每组 32 个元素提取共享指数后量化为 FP8 目标类型(FLOAT8_E5M2 或 FLOAT8_E4M3FN),同时输出 FLOAT8_E8M0 缩放因子。量化后的数据将作为 GMM1 的输入。第二阶段对每个专家执行 GMM1 矩阵乘法(将 W1W_1 沿列方向分为两半分别计算)、Activation 和 MX 量化:
Ge=DQMX(X^e,SX,e)⋅DQMX(W1,e(G),S1,e(G)),Ue=DQMX(X^e,SX,e)⋅DQMX(W1,e(U),S1,e(U))G_e = \mathrm{DQ}_{\text{MX}}(\hat{X}_e, S_{X,e}) \cdot \mathrm{DQ}_{\text{MX}}(W_{1,e}^{(G)}, S_{1,e}^{(G)}), \quad U_e = \mathrm{DQ}_{\text{MX}}(\hat{X}_e, S_{X,e}) \cdot \mathrm{DQ}_{\text{MX}}(W_{1,e}^{(U)}, S_{1,e}^{(U)})
Ae=Activation(Ge,Ue)A_e = \operatorname{Activation}(G_e,U_e)
A^e, SA,e=QMX(Ae)\hat{A}_e,\ S_{A,e} = \mathrm{Q}_{\text{MX}}(A_e)
说明:将 W1W_1 的前 N/2N/2 列 W1,e(G)W_{1,e}^{(G)} 和后 N/2N/2 列 W1,e(U)W_{1,e}^{(U)} 分别与 MX 反量化后的输入做矩阵乘法,得到 gate 分支 GeG_e 和 up 分支 UeU_e。具体激活函数的计算方式参见激活函数公式,其输出维度为 N/2N/2。随后对激活输出做 MX 量化,量化类型与 Dispatch 阶段的量化类型一致,即同为
FLOAT8_E5M2或同为FLOAT8_E4M3FN,得到 GMM2 的量化输入 A^e\hat{A}_e。第三阶段对每个专家执行 GMM2 矩阵乘法,并将结果按目标 Rank 分发:
Oe=DQMX(A^e,SA,e)⋅DQMX(W2,e,S2,e)O_e = \mathrm{DQ}_{\text{MX}}(\hat{A}_e, S_{A,e}) \cdot \mathrm{DQ}_{\text{MX}}(W_{2,e}, S_{2,e})
说明:将量化后的激活输出与第二组权重 W2W_2 做 MX 反量化后的矩阵乘法,将 N/2N/2 维中间表示映射回 HH 维隐藏空间,得到每个专家的输出 OeO_e。计算完成后通过 RDMA peermem 将结果按目标 Rank 的专家偏移地址写入远端,实现跨 Rank 聚合。
当启用共享专家(
sharedExpertNumPerRank> 0)时,共享专家在每张卡上对本卡全部 token 本地执行与路由专家相同的 GMM1 + Activation + GMM2 计算,使用sharedWeight1、sharedWeight2、sharedWeightScales1、sharedWeightScales2,无需参与 Dispatch 通信。各共享专家的输出记为 OssharedO^{\mathrm{shared}}_s,s∈{0,…,sharedExpertNumPerRank−1}s \in \{0, \dots, \text{sharedExpertNumPerRank} - 1\}。第四阶段对所有 Token 按路由权重加权求和,并叠加共享专家输出,恢复为与输入相同形状的输出:
Y[i]=∑k=0K−1W[i, k]⋅O[π(i, k)]+∑s=0sharedExpertNumPerRank−1Osshared[i]Y[i] = \sum_{k=0}^{K-1} W[i,\, k] \cdot O[\pi(i,\, k)] + \sum_{s=0}^{\text{sharedExpertNumPerRank}-1} O^{\mathrm{shared}}_s[i]
说明:对每个 Token ii,根据排序后的路由索引 π(i,k)\pi(i,k) 从聚合后的专家结果中取出对应行,按
topkWeights中的权重逐元素加权累加,再直接加上各共享专家对当前 token 的输出,得到最终输出 YY。未启用共享专家时,共享专家求和项为零。其中,XX 表示参数
x,WW 表示参数topkWeights,W1W_1 表示参数weight1,W2W_2 表示参数weight2,YY 表示参数y,ElocalE_{\text{local}} 表示localMoeExpertNum = moeExpertNum / epWorldSize(每个 Rank 的路由 MoE 专家数),KK 表示topkIds的第二维度。局部变量说明:
- Te\mathcal{T}_e:被路由到专家 ee 的 Token 索引集合,由
topkIds排序后确定。 - me=∣Te∣m_e=|\mathcal{T}_e|:专家 ee 本次实际接收的 Token 数,不同专家的 mem_e 可以不同。
- X^e, SX,e\hat{X}_e,\ S_{X,e}:专家 ee 的量化输入及其 MX 缩放因子,第一阶段中间结果。
- W1,e(G)W_{1,e}^{(G)}、W1,e(U)W_{1,e}^{(U)}:W1W_1 对应专家 ee 的前 N/2N/2 列和后 N/2N/2 列子矩阵,由
weight1按 gate 分支和 up 分支拆分推导。 - S1,e(G)S_{1,e}^{(G)}、S1,e(U)S_{1,e}^{(U)}:W1,e(G)W_{1,e}^{(G)} 和 W1,e(U)W_{1,e}^{(U)} 对应的 MX 缩放因子,从
weightScales1按维度截取。 - S2,eS_{2,e}:W2,eW_{2,e} 对应的 MX 缩放因子,来自参数
weightScales2。 - Ge, UeG_e,\ U_e:GMM1 的 gate 分支和 up 分支输出,中间结果。
- AeA_e:激活输出,维度 me×N/2m_e \times N/2,中间结果。
- A^e, SA,e\hat{A}_e,\ S_{A,e}:量化后的激活输出及其 MX 缩放因子,中间结果。
- OeO_e:GMM2 的专家级输出,维度 me×Hm_e \times H,中间结果。
- π(i,k)\pi(i, k):Token ii 的第 kk 个 top-k 专家在展开排序后的行索引,由路由排序确定。
- QMX(⋅)\mathrm{Q}_{\text{MX}}(\cdot):MX 逐组量化操作,block size = 32,输出 FP8 数据和 E8M0 缩放因子。
- DQMX(⋅)\mathrm{DQ}_{\text{MX}}(\cdot):MX 逐组反量化操作,在 matmul 内部隐式执行。
A8W4-FP 量化场景
第一阶段(Token 选择、量化与 Dispatch):
对本 rank 的输入 Token X∈RB×HX \in \mathbb{R}^{B\times H},根据
topkIds得到每个专家 ee 对应的 Token 下标集合 TeT_e,并将选中的 BF16 Token 按 32 个元素一组量化为 MXFP8 E4M3:X^e, SX,e=QMX (X[Te]),\hat{X}_e,\;S_{X,e} = \mathrm{Q}_{\mathrm{MX}}\!\left(X[T_e]\right),
其中,X^e\hat{X}_e 的数据类型为
FLOAT8_E4M3FN,SX,eS_{X,e} 的数据类型为FLOAT8_E8M0。随后将量化后的 Token 及其缩放因子发送到专家所在 rank。路由 MoE 专家的第一层和第二层权重 W1,eW_{1,e}、W2,eW_{2,e} 均为 MXFP4 E2M1 数据,缩放因子为 E8M0,ee 的范围为 [0,localMoeExpertNum)[0,\text{localMoeExpertNum})。共享专家权重单独由
sharedWeight1、sharedWeight2提供,其第一维为sharedExpertNumPerRank。A8W4 kernel 在矩阵乘 Prologue 中处理 FP4 权重,送入矩阵乘的逻辑数据流为 FP8 激活乘 FP4 权重。第二阶段(GMM1、Activation 与再次量化):
对专家 ee 收到的 Token,第一层分组矩阵乘和激活函数计算为:
Ge=DQMX (X^e,SX,e)⋅DQMX (W1,e(G),S1,e(G)),G_e = \mathrm{DQ}_{\mathrm{MX}}\!\left(\hat{X}_e,S_{X,e}\right) \cdot \mathrm{DQ}_{\mathrm{MX}}\!\left(W_{1,e}^{(G)},S_{1,e}^{(G)}\right),
Ue=DQMX (X^e,SX,e)⋅DQMX (W1,e(U),S1,e(U)),U_e = \mathrm{DQ}_{\mathrm{MX}}\!\left(\hat{X}_e,S_{X,e}\right) \cdot \mathrm{DQ}_{\mathrm{MX}}\!\left(W_{1,e}^{(U)},S_{1,e}^{(U)}\right),
Ae=Activation(Ge,Ue).A_e = \operatorname{Activation}(G_e,U_e).
具体激活函数的计算方式参见激活函数公式。其输出继续按 32 个元素一组量化为 MXFP8 E4M3,与 Dispatch 阶段的量化类型一致,均为
FLOAT8_E4M3FN,供第二层矩阵乘使用:A^e, SA,e=QMX (Ae).\hat{A}_e,\;S_{A,e} = \mathrm{Q}_{\mathrm{MX}}\!\left(A_e\right).
第三阶段(GMM2):
第二层矩阵乘仍为 A8W4,即 FP8 E4M3 激活乘 FP4 E2M1 权重:
Oe=DQMX (A^e,SA,e)⋅DQMX (W2,e,S2,e).O_e = \mathrm{DQ}_{\mathrm{MX}}\!\left(\hat{A}_e,S_{A,e}\right) \cdot \mathrm{DQ}_{\mathrm{MX}}\!\left(W_{2,e},S_{2,e}\right).
当启用共享专家(
sharedExpertNumPerRank> 0)时,共享专家在每张卡上对本卡全部 token 本地执行与路由专家相同的 GMM1 + Activation + GMM2 计算,使用sharedWeight1、sharedWeight2、sharedWeightScales1、sharedWeightScales2,无需参与 Dispatch 通信。各共享专家的输出记为 OssharedO^{\mathrm{shared}}_s,s∈{0,…,sharedExpertNumPerRank−1}s \in \{0, \dots, \text{sharedExpertNumPerRank} - 1\}。第四阶段(Combine 与加权合并):
将各专家输出送回原 rank,并根据
topkWeights做加权合并,并叠加共享专家输出:Y[i]=∑k=0K−1W[i,k]⋅O[π(i,k)]+∑s=0sharedExpertNumPerRank−1Osshared[i],Y[i] = \sum_{k=0}^{K-1} W[i,k] \cdot O[\pi(i,k)] + \sum_{s=0}^{\text{sharedExpertNumPerRank}-1} O^{\mathrm{shared}}_s[i],
未启用共享专家时,共享专家求和项为零。最终输出 YY 的数据类型为 BF16。A8W4-FP 的主要数据类型流为:
BF16 -> MXFP8 E4M3 -> A8W4 GMM1 -> MXFP8 E4M3 -> A8W4 GMM2 -> BF16。A4W4-FP 量化场景
第一阶段(Token 选择、量化与 Dispatch):
对每个专家 ee 对应的 Token 集合 TeT_e,将选中的 BF16 Token 按 32 个元素一组量化为 MXFP4 E2M1:
X^e, SX,e=QMX (X[Te]),\hat{X}_e,\;S_{X,e} = \mathrm{Q}_{\mathrm{MX}}\!\left(X[T_e]\right),
其中,X^e\hat{X}_e 的数据类型为
FLOAT4_E2M1,SX,eS_{X,e} 的数据类型为FLOAT8_E8M0。路由 MoE 专家的第一层和第二层权重 W1,eW_{1,e}、W2,eW_{2,e} 均为 MXFP4 E2M1,ee 的范围为 [0,localMoeExpertNum)[0,\text{localMoeExpertNum});共享专家权重的第一维为sharedExpertNumPerRank。权重缩放因子为 E8M0。第二阶段(A4W4 GMM1、Activation 与激活后量化):
第一层分组矩阵乘为 A4W4:
Ge=DQMX (X^e,SX,e)⋅DQMX (W1,e(G),S1,e(G)),G_e = \mathrm{DQ}_{\mathrm{MX}}\!\left(\hat{X}_e,S_{X,e}\right) \cdot \mathrm{DQ}_{\mathrm{MX}}\!\left(W_{1,e}^{(G)},S_{1,e}^{(G)}\right),
Ue=DQMX (X^e,SX,e)⋅DQMX (W1,e(U),S1,e(U)),U_e = \mathrm{DQ}_{\mathrm{MX}}\!\left(\hat{X}_e,S_{X,e}\right) \cdot \mathrm{DQ}_{\mathrm{MX}}\!\left(W_{1,e}^{(U)},S_{1,e}^{(U)}\right),
Ae=Activation(Ge,Ue).A_e = \operatorname{Activation}(G_e,U_e).
具体激活函数的计算方式参见激活函数公式。A4W4-FP 场景下,第一层矩阵乘后的激活结果按 32 个连续元素一组量化为 MXFP8 E4M3,缩放因子为 E8M0,并作为第二层矩阵乘的输入。该设计用于避免两层矩阵乘均采用 A4W4 带来较大的精度损失:
A^e, SA,e=QMX (Ae).\hat{A}_e,\;S_{A,e} = \mathrm{Q}_{\mathrm{MX}}\!\left(A_e\right).
第三阶段(A8W4 GMM2):
由于激活输出量化后为 FP8 E4M3,而第二层权重仍为 FP4 E2M1,因此第二层矩阵乘实际为 A8W4,而不是 A4W4:
Oe=DQMX (A^e,SA,e)⋅DQMX (W2,e,S2,e).O_e = \mathrm{DQ}_{\mathrm{MX}}\!\left(\hat{A}_e,S_{A,e}\right) \cdot \mathrm{DQ}_{\mathrm{MX}}\!\left(W_{2,e},S_{2,e}\right).
当启用共享专家(
sharedExpertNumPerRank> 0)时,共享专家在每张卡上对本卡全部 token 本地执行与路由专家相同的 GMM1 + Activation + GMM2 计算,使用sharedWeight1、sharedWeight2、sharedWeightScales1、sharedWeightScales2,无需参与 Dispatch 通信。各共享专家的输出记为 OssharedO^{\mathrm{shared}}_s,s∈{0,…,sharedExpertNumPerRank−1}s \in \{0, \dots, \text{sharedExpertNumPerRank} - 1\}。第四阶段(Combine 与加权合并):
Y[i]=∑k=0K−1W[i,k]⋅O[π(i,k)]+∑s=0sharedExpertNumPerRank−1Osshared[i],Y[i] = \sum_{k=0}^{K-1} W[i,k] \cdot O[\pi(i,k)] + \sum_{s=0}^{\text{sharedExpertNumPerRank}-1} O^{\mathrm{shared}}_s[i],
未启用共享专家时,共享专家求和项为零。最终输出 YY 的数据类型为 BF16。A4W4-FP 的完整数据类型流为:
BF16 -> MXFP4 E2M1 -> A4W4 GMM1 -> MXFP8 E4M3 -> A8W4 GMM2 -> BF16。其中所有 MX 缩放因子的类型均为FLOAT8_E8M0,量化粒度均为 32 个连续元素。
参数说明
| 参数名 | 输入/输出/属性 | 描述 | 数据类型 | 数据格式 |
|---|---|---|---|---|
| context | 输入 | 本卡通信域信息数据。 | INT32 | ND |
| x | 输入 | MoE层输入的token隐藏状态。shape为(BS, H),H为逻辑隐藏维,与weight1的最后一维一致。除预量化直通场景外,x的数据类型必须为BF16,量化(若有)由算子内部完成;预量化直通场景(dispatchQuantMode为0且dispatchQuantOutDtype为FLOAT8_E5M2、FLOAT8_E4M3FN或FLOAT4_E2M1)下算子内部不做量化,此时x的数据类型必须与dispatchQuantOutDtype指定的逻辑类型一致,并且必须同时传入scales。各产品支持的数据类型详见约束说明。 | BF16、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1 | ND |
| topkIds | 输入 | 专家索引矩阵,表示每个token选择的topK个专家。元素取值范围为[0, moeExpertNum),且同一token选择的topK个专家不能重复。 | INT32 | ND |
| topkWeights | 输入 | 表示MoE模型的专家门控网络为当前输入Token选出的topK个专家所对应的门控权重系数。 | FP32、BF16 | ND |
| weight1 | 输入 | MoE专家网络第一线性层的权重矩阵(包括门控与上投影),用于将输入映射至中间维度,输出供给激活函数。路由 MoE 专家数为 localMoeExpertNum。 |
BF16、INT8、INT4、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1 | ND、FRACTAL_NZ、FORMAT_FRACTAL_NZ_C0_32 |
| weight2 | 输入 | MoE专家网络第二线性层的权重矩阵,负责将激活后的中间特征投影回隐藏维度。数据类型与weight1一致。路由 MoE 专家数为 localMoeExpertNum。 |
BF16、INT8、INT4、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1 | ND、FRACTAL_NZ、FORMAT_FRACTAL_NZ_C0_32 |
| weightScales1 | 可选输入 | MoE专家网络第一线性层的权重矩阵的量化缩放因子。MXFP量化场景下必须输入。 | FLOAT8_E8M0、UINT64 | ND |
| weightScales2 | 可选输入 | MoE专家网络第二线性层的权重矩阵的量化缩放因子。MXFP量化场景下必须输入。 | FLOAT8_E8M0、UINT64 | ND |
| bias1 | 可选输入 | MoE专家网络第一线性层的偏置,仅于A8W4-INT量化场景下需要该参数,用于精度补偿。 | FP32 | ND |
| bias2 | 可选输入 | MoE专家网络第二线性层的偏置,仅于A8W4-INT量化场景下需要该参数,用于精度补偿。 | FP32 | ND |
| xActiveMask | 可选输入 | 表示token是否参与通信。 | INT8 | ND |
| scales | 可选输入 | x的反量化缩放因子,给出x各量化组对应的缩放值。预量化直通场景(dispatchQuantMode为0且dispatchQuantOutDtype为FLOAT8_E5M2、FLOAT8_E4M3FN或FLOAT4_E2M1)下必选,shape为(BS, CeilDiv(H, 32)),数据类型必须为FLOAT8_E8M0;其余场景必须传入空指针。各产品支持情况详见约束说明。 | FLOAT8_E8M0、FLOAT32 | ND |
| sharedWeight1 | 可选输入 | 共享专家网络第一线性层的权重矩阵(包括门控与上投影),用于将输入映射至中间维度,输出供给激活函数。数据类型可以与MoE专家第一线性层权重weight1不同,支持MoE专家与共享专家采用不同的权重类型与量化类型(如MoE专家W8配共享专家W4、MoE专家W4配共享专家W8);sharedWeight1与sharedWeight2的数据类型必须一致。 | FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1 | ND、FRACTAL_NZ、FORMAT_FRACTAL_NZ_C0_32 |
| sharedWeight2 | 可选输入 | 共享专家网络第二线性层的权重矩阵,负责将激活后的中间特征投影回隐藏维度。数据类型可以与MoE专家第二线性层权重weight2不同,取值要求同sharedWeight1。 | FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1 | ND、FRACTAL_NZ、FORMAT_FRACTAL_NZ_C0_32 |
| sharedWeightScales1 | 可选输入 | 共享专家网络第一线性层的权重矩阵的量化缩放因子。 | FLOAT8_E8M0 | ND |
| sharedWeightScales2 | 可选输入 | 共享专家网络第二线性层的权重矩阵的量化缩放因子。 | FLOAT8_E8M0 | ND |
| sharedBias1 | 可选输入 | 共享专家网络第一线性层的偏置,暂不支持。 | FP32 | ND |
| sharedBias2 | 可选输入 | 共享专家网络第二线性层的偏置,暂不支持。 | FP32 | ND |
| moeExpertNum | 属性 | MoE模型的总专家数量。 | INT64 | |
| epWorldSize | 属性 | 专家并行通信域大小。 | INT64 | |
| cclBufferSize | 属性 | CCL通信缓冲区大小。 | INT64 | |
| maxRecvTokenNum | 可选属性 | 每个Rank最大可接收Token数。默认值为0。该值为0时,会按最大值bs*epWorldSize*min(topK,localMoeExpertNum)预留内存大小;不为0时,将按照输入值大小预留内存,该场景下需用户保证填入值大于等于每个rank最大可接收的Token数。 | INT64 | |
| dispatchQuantMode | 可选属性 | dispatch通信时量化模式。0表示算子内部不做dispatch量化,2表示INT8 pertoken量化,4表示算子内部执行MX逐组量化。默认值为0。各产品支持的取值、对应的计算场景以及取值0的具体含义详见约束说明。 | INT64 | |
| dispatchQuantOutDtype | 可选属性 | dispatch量化后输出的数据类型。支持1(INT8)、23(FLOAT8_E5M2)、24(FLOAT8_E4M3FN)、296(FLOAT4_E2M1)。默认值为DT_UNDEFINED。dispatchQuantMode为4时该属性表示算子内量化的输出类型;预量化直通场景(dispatchQuantMode为0且该属性为23、24或296)下表示预量化x的逻辑类型,此时必须与x的实际数据类型一致。各产品实际支持的取值范围详见约束说明。 | INT64 | |
| sharedExpertQuantOutDtype | 可选属性 | 共享专家输入的量化数据类型。默认值为DT_UNDEFINED,表示与dispatchQuantOutDtype保持一致;显式配置时支持23(FLOAT8_E5M2)、24(FLOAT8_E4M3FN)、296(FLOAT4_E2M1),用于共享专家与MoE专家采用不同量化配置的场景。预量化直通(dispatchQuantMode为0)场景下只能取DT_UNDEFINED或与dispatchQuantOutDtype相同。 | INT64 | |
| combineQuantMode | 可选属性 | combine通信时的量化模式。0表示非量化,3表示MXFP float8_e5m2类型,4表示MXFP float8_e4m3类型, 默认值为0。 | INT64 | |
| commAlg | 可选属性 | 预留参数,保持默认值即可。默认值为""。 | STRING | |
| numMaxTokensPerRank | 可选属性 | 每张卡上的token数量。当每个rank的numTokens不同时,为最大的numTokens大小。默认值为0。 | INT64 | |
| activation | 可选属性 | 激活函数类型。默认值为"swiglu"。可选值为"swiglu"、"swiglustep"、"swigluoai"和"situglu"。 | STRING | |
| activation_params | 可选属性 | 激活函数参数列表,默认值为[]。参数顺序和数量由activation决定:"swiglu"和"swiglustep"支持[]或[clamp];"swigluoai"支持[]或[clamp, alpha, beta];"situglu"支持[]、[beta]或[beta, linear_beta]。使用空列表时,clamp默认为float最大值,alpha默认为1.702,swigluoai的beta默认为1.0。clamp需≥0且不能为NaN;alpha和swigluoai的beta需为有限值;situglu实际使用的beta以及显式配置的linear_beta均需为大于0的有限值。各产品对"situglu"参数列表的支持差异详见约束说明。 | LIST_FLOAT | |
| activationOutDtype | 可选属性 | 激活函数输出的数据类型。默认值为DT_UNDEFINED。 | INT64 | |
| transposeWeight1 | 可选属性 | weight1是否转置。默认值为false。 | BOOL | |
| transposeWeight2 | 可选属性 | weight2是否转置。默认值为false。 | BOOL | |
| weight1Interleave | 可选属性 | weight1交错参数。预留参数,默认值为0。 | INT64 | |
| topoType | 可选属性 | 通信拓扑类型,由通信域上下文自动推导。0表示MTE拓扑,1表示URMA跨超拓扑。默认值为0。 | INT64 | |
| rankNumPerServer | 可选属性 | 每台server上的rank数量,最少为2。默认值为2。该属性在部分产品的部分通信拓扑下不生效,详见约束说明。 | INT64 | |
| topkWeightsType | 可选属性 | topkWeights前移开关。0表示关闭,1表示开启(将topkWeights随token数据一起在dispatch阶段提前发送至目标rank,减少combine阶段通信量)。默认值为0。 | INT64 | |
| combineCommMode | 可选属性 | combine阶段通信去重开关。0表示关闭,1表示开启(同一token在本卡命中的多个专家,其combine结果先在本卡合并为一行再发回源卡,combine阶段通信量从组内行数降为1)。取值仅支持0或1,是否开启完全由调用方按形状决定,算子内部不做收益裁决。开启会改变通信记录布局,所有Rank必须配置相同取值。默认值为0。各产品与通信拓扑对该开关的支持范围详见约束说明。 | INT64 | |
| y | 输出 | 计算输出结果。shape为(BS, H),与x的shape一致。数据类型详见约束说明。 | BF16 | ND |
| expertTokenNums | 输出 | 本卡每个专家实际收到的token数量。 | INT32 | ND |
约束说明
-
预留和非对外参数说明:
- 参数表格中的部分参数、部分数据类型暂未对外提供,为预留或内部实现使用。接口参数的介绍及其约束在接口文档MegaMoE算子接口文档中详细说明。
-
参数一致性约束:
- 调用算子过程中使用的
moeExpertNum、maxRecvTokenNum、dispatchQuantMode、dispatchQuantOutDtype、numMaxTokensPerRank、topkWeightsType、combineCommMode等参数取值,所有卡需保持一致,网络中不同层中也需保持一致。其中topkWeightsType与combineCommMode决定通信记录的布局,跨卡取值不一致会导致读写错位。
- 调用算子过程中使用的
-
通信域约束:
- 所有卡的
epWorldSize、cclBufferSize参数取值需保持一致。 - 通信域各节点的驱动版本应当相同。
- Ascend 950PR&950DT系列产品:Torch接口通过
get_symm_buffer_for_mega_moe自动计算并申请通信buffer,用户无需自行计算或设置cclBufferSize。
- 所有卡的
-
组网约束:
- Atlas A2系列产品:多机通信域要求交换机组网,不支持双机直连组网。
- Atlas A3系列产品:多机通信域要求在一个超节点内,不支持双机直连组网和跨超节点组网。
- Ascend 950PR&950DT系列产品:仅支持UB Memory通信协议。
-
参数约束:
-
Atlas A2系列产品、Atlas A3系列产品:
-
场景配套矩阵:
场景 x weight1 weight2 weightScales1 weightScales2 bias1 bias2 y dispatchQuantMode dispatchQuantOutDtype A16W16 BF16 BF16 BF16 – – – – BF16 0 – A8W8-INT BF16 INT8 INT8 UINT64 UINT64 – – BF16 2 1(INT8) A8W4-INT BF16 INT4(INT32) INT4(INT32) UINT64 UINT64 FP32 FP32 BF16 2 1(INT8) -
dispatchQuantMode仅支持0和2,0对应A16W16场景(算子内部不做dispatch量化),2对应A8W8-INT、A8W4-INT场景(INT8 pertoken量化)。dispatchQuantMode与dispatchQuantOutDtype的取值由weight1的数据类型唯一确定,取值不匹配时算子在tiling阶段报错:weight1为INT4或INT8时分别取2与1(INT8);weight1为BF16或FLOAT16时分别取0与weight1相同的数据类型。dispatchQuantOutDtype传DT_UNDEFINED时不做该校验,各场景的对应取值见上表。 -
scales为预留输入,当前必须传入空指针。 -
activation为"situglu"时,activation_params支持[]、[beta]或[beta, linear_beta];使用空列表时beta默认为1.0且linear_beta不启用。 -
不支持combine阶段通信去重,
combineCommMode必须保持默认值0。 -
y的数据类型与x一致。
-
-
Ascend 950PR&950DT系列产品:
activation支持"swiglu"、"swiglustep"、"swigluoai"和"situglu";其中"situglu"的activation_params必须显式给出,仅支持[beta]或[beta, linear_beta],不支持空列表。其余激活的参数配套关系见参数说明。BS为本Rank本次调用的x.dim0,支持[1, +∞),且不得超过创建sym_buffer时设置的numMaxTokensPerRank。不同Rank的实际BS可以不同,同一sym_buffer可以复用于多次不同BS的调用。numMaxTokensPerRank必须大于等于1且所有Rank配置一致,建议设置为sym_buffer复用期间所有Rank可能出现的最大单卡BS。设置越大,内部申请的通信内存越多。H(x.dim1)范围[1024, 8192]。topoType= 0(MTE拓扑)下各量化场景均要求H为64的倍数;topoType= 1(URMA跨超拓扑)要求H为1024的倍数。A4W4-FP场景仅支持weight1为FRACTAL_NZ格式。topK(topkIds.dim1)支持[1, 32]。localMoeExpertNum(=moeExpertNum/epWorldSize)范围 [1, 1024];共享专家数sharedExpertNumPerRank另按 [0, 4] 单独约束,不计入该上限。intermediateHidden表示激活后的中间特征维度,范围[256, 4096]且128对齐;weight1的完整输出宽度为2 ×intermediateHidden。epWorldSize范围 [2, 1024]。moeExpertNum范围 [epWorldSize, 2048],且moeExpertNum%epWorldSize== 0。maxRecvTokenNum范围 [0,numMaxTokensPerRank×epWorldSize× min(topK,localMoeExpertNum)],建议保持默认值0,由接口自动计算接收容量。dispatchQuantOutDtype仅支持23(FLOAT8_E5M2)或24(FLOAT8_E4M3FN)或296(FLOAT4_E2M1)。dispatchQuantMode取值为0或4。4表示算子内部对BF16的x做MX逐组量化(group size = 32,量化缩放因子类型为FLOAT8_E8M0),对应A8W8-FP、A8W4-FP、A4W4-FP场景;0表示预量化直通,即x已经是量化后的数据、算子内部不再量化,缩放因子由scales入参给出。- 预量化直通(
dispatchQuantMode= 0)的约束:x的数据类型必须与dispatchQuantOutDtype指定的逻辑类型一致;scales为必选;仅支持topoType= 0(MTE拓扑);sharedExpertQuantOutDtype只能取DT_UNDEFINED或与dispatchQuantOutDtype相同。 combineQuantMode取值为0、3、4,0表示非量化,3表示MXFP float8_e5m2类型,4表示MXFP float8_e4m3类型commAlg为预留参数,请保持默认空字符串""。y的数据类型固定为BF16。weight1的Linear1输出维必须等于2 ×intermediateHidden,weight2的输入维必须等于intermediateHidden。localMoeExpertNum=moeExpertNum/epWorldSize;sharedExpertNumPerRank=sharedWeight1.dim0(未启用共享专家时为0);expertPerRank=sharedExpertNumPerRank+localMoeExpertNum。sharedExpertNumPerRank范围 [0, 4]。topoType由通信域上下文自动推导。0表示MTE拓扑,1表示URMA跨超拓扑。- MTE拓扑(
topoType= 0)下rankNumPerServer不生效,算子内部按epWorldSize处理。 - URMA拓扑下,
activation不支持swiglustep和swigluoai。 topkWeightsType取值为0或1,0表示关闭topkWeights前移,1表示开启。combineCommMode取值为0或1,0表示关闭combine阶段通信去重,1表示开启。是否开启完全由调用方决定,算子内部不做收益裁决;所有Rank必须配置相同取值,否则跨卡的通信记录布局不一致会导致读写错位。适用场景:topK较大、同一token命中同卡多个专家的比例较高、性能瓶颈在通信的形状,开启后收益明显;专家数多且瓶颈在计算的形状可能没有收益甚至变慢,建议按实际形状实测后再决定。combineCommMode= 1时的能力约束(不满足时算子在tiling阶段直接报错并提示改回0,不做静默回退):仅支持topoType= 0(MTE拓扑);combineQuantMode必须为0(combine不量化);topkWeightsType= 0时不支持预量化x;numMaxTokensPerRank需满足numMaxTokensPerRank≤ 128 × min(512, ⌊4608 /topK⌋)(例如topK= 32时上限为18432,topK≤ 9时上限为65536)。combineCommMode= 1时,同一token在同一张卡上的多个专家输出改为在该卡按FP32累加后一次转BF16发送,累加顺序与中间取整次数与关闭态不同,因此y与combineCommMode= 0的结果不逐位相同,差异属BF16累加顺序不同带来的正常误差;需要与关闭态逐位一致时请使用combineCommMode= 0。weightScales1和weightScales2为必选输入,数据类型必须为FLOAT8_E8M0。weight1和weight2的数据类型必须一致,且仅支持FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1。此处的「一致」指同一专家组内部一致,MoE专家与共享专家之间可以采用不同的权重类型与量化类型。- MoE专家与共享专家的量化配置不同时,仅
topoType= 0(MTE拓扑)支持。 topkWeights数据类型仅支持BF16或FP32。xActiveMask当前版本不支持非空输入,需传入空指针。scales仅在预量化直通(dispatchQuantMode= 0且dispatchQuantOutDtype为FLOAT8_E5M2、FLOAT8_E4M3FN或FLOAT4_E2M1)场景为必选,shape为(BS, CeilDiv(H, 32)),数据类型必须为FLOAT8_E8M0;其余场景必须传入空指针。
-
MXFP量化场景约束:
weight1shape为(localMoeExpertNum, 2 ×intermediateHidden,H),weight2shape为(localMoeExpertNum,H,intermediateHidden)。weightScales1shape为(localMoeExpertNum, 2 ×intermediateHidden, CeilDiv(H, 64), 2)。weightScales2shape为(localMoeExpertNum,H, CeilDiv(intermediateHidden, 64), 2)。sharedWeight1shape为(sharedExpertNumPerRank, 2 ×intermediateHidden,H),sharedWeight2shape为(sharedExpertNumPerRank,H,intermediateHidden)。sharedWeightScales1shape为(sharedExpertNumPerRank, 2 ×intermediateHidden, CeilDiv(H, 64), 2),sharedWeightScales2shape为(sharedExpertNumPerRank,H, CeilDiv(intermediateHidden, 64), 2)。weightScales1的dim3和weightScales2的dim3必须等于2。- A8W4-FP场景下,FLOAT4_E2M1类型的
weight1必须使用FORMAT_FRACTAL_NZ_C0_32格式;A4W4-FP场景下,FLOAT4_E2M1类型的weight1必须使用FRACTAL_NZ格式。两种场景的weight2均必须使用FORMAT_FRACTAL_NZ_C0_32格式。启用共享专家时,sharedWeight1和sharedWeight2的格式按共享专家自身的量化类型确定(W8走ND或FRACTAL_NZ、W4走FRACTAL_NZ或FORMAT_FRACTAL_NZ_C0_32),与weight1、weight2的格式可以不同。 - A8W8-FP场景下,
weight1和weight2必须同为FLOAT8_E5M2或同为FLOAT8_E4M3FN。A8W4-FP和A4W4-FP场景下,两层权重均为FLOAT4_E2M1。 - 权重及其scale支持两种TensorList布局。对于
weight1、weight2、weightScales1和weightScales2,逐专家布局下四个TensorList的长度均为localMoeExpertNum,权重列表中的Tensor为二维,权重scale列表中的Tensor为三维;堆叠布局下四个TensorList的长度均为1,权重Tensor为三维,权重scale Tensor为四维,且各Tensor的dim0均为localMoeExpertNum。四个输入必须采用同一种布局;启用共享专家时,对应的四个共享专家输入也必须采用与MoE专家相同的布局。
-
调用说明
| 调用方式 | 样例代码 | 说明 |
|---|---|---|
| PyTorch接口调用 | - | 通过mega_moePyTorch接口方式调用mega_moe算子。 |