Repository navigation
[MoE] Compute the gate GEMM in bf16 on tensor cores - #2
Merged
Merged
Conversation
The gate converted x and its weight to fp32 and ran an fp32 SIMT GEMM. On CUDA it now multiplies the bf16 inputs on tensor cores with fp32 output (torch.mm out_dtype), as DeepInfer's gate does; scoring, top-k and normalization stay in fp32. CPU keeps the fp32 path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 24, 2026
algebra-MCX
force-pushed
the
perf/bf16-gate
branch
from
October 24, 2026 06:24
555d5f5 to
048e6e3
Compare
algebra-MCX
added a commit
that referenced
this pull request
Oct 26, 2026
[MoE] Compute the gate GEMM in bf16 on tensor cores
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
English · click to expand
Motivation
The MoE gate takes about 76 ms per prefill step; the official DeepInfer takes 1.2 ms. The gate casts
xand its weight to fp32 and runs an fp32 SIMT GEMM, which alone costs about 49 ms per step.Change
On CUDA,
Gate.forwardusestorch.mm(x, weight.t(), out_dtype=torch.float32): bf16 inputs on tensor cores, fp32 output. Scoring, top-k and normalization stay fp32. The numerics match DeepInfer's gate (bf16 in, fp32 out). CPU does not supportout_dtype, so it keeps the fp32 path.Size:
model.py+5/−1; one new test intests/test_moe.py(3 scoring functions).Validation
pytest -q -m "not gpu"(CPU): 35 passedpython -m compileall -q deepinfer_lab testsgit diff --checktests/test_moe.py: 16 passed, including the new test. V4.1-Flash gate shape (5120 → 384, top-6), 300 tokens: bf16 and fp32 pick identical experts, weight error < 1e-4tests/test_cuda_graph.py,tests/test_sync_free.py: 20 passed together withtest_moe.py. The decode CUDA graph captures it; no host sync in the forwardtests/test_v41.py,tests/test_engine.py: 17 passed. Tiny model vs DeepSeek's reference implementation; logit gap still < 0.05Measurement
Job 9816: 4 × B200, real V4.1-Flash, EP4 / DP4 / CP1, 131,072-token context (126,976 cached), 4,096 new tokens per rank per step, 10 steady-state steps per run, no CUDA graph. The three revisions alternate in one job:
main→ gate → attention → attention → gate →main.mainmain(2818d6e)048e6e3)ba0c0d3)Conflicts & rollback
base
main(2818d6e), headperf/bf16-gate, no conflicts. Revert the single commit to roll back.Related
Closes #4 · Roadmap: #3 (MoE)
简体中文 · 点击展开
动机
MoE gate 在 prefill 中每步约 76 ms,官方 DeepInfer 为 1.2 ms。原因是 gate 把
x和权重转成 fp32,再做 fp32 SIMT 矩阵乘;仅这一个 kernel 每步就约 49 ms。方案
Gate.forward在 CUDA 上改用torch.mm(x, weight.t(), out_dtype=torch.float32):bf16 输入走 tensor core,输出 fp32。打分、top-k、归一化不变,仍为 fp32。数值上与 DeepInfer 的 gate 一致(bf16 输入、fp32 输出)。CPU 不支持out_dtype,保留原 fp32 路径。改动:
model.py+5/−1,tests/test_moe.py新增 1 个测试(3 种打分函数)。验证
pytest -q -m "not gpu"(CPU):35 passedpython -m compileall -q deepinfer_lab testsgit diff --checktests/test_moe.py:16 passed,含新测试。V4.1-Flash 的 gate 尺寸(5120 → 384,top-6),300 个 token:bf16 与 fp32 选出的专家完全相同,权重误差 < 1e-4tests/test_cuda_graph.py、tests/test_sync_free.py:与test_moe.py合计 20 passed。decode CUDA graph 能捕获,forward 中没有 host 同步tests/test_v41.py、tests/test_engine.py:17 passed。tiny 模型对照 DeepSeek 参考实现,logits 差距仍 < 0.05实测
作业 9816:4 × B200,真实 V4.1-Flash,EP4 / DP4 / CP1,131,072-token 上下文(126,976 已缓存),每步每卡新增 4,096 token,每轮 10 个稳态步,未启用 CUDA graph。三个版本在同一作业内按
main→ gate → 注意力 → 注意力 → gate →main交替运行。mainmain(2818d6e)048e6e3)ba0c0d3)冲突与回滚
base
main(2818d6e),headperf/bf16-gate,无冲突。若有问题,回退这一个提交即可。关联
Closes #4 · 路线图:#3(MoE)