💎使用 Unsloth 将 MoE 模型微调速度提高 12 倍
使用 Unsloth 在本地训练 MoE LLM 的指南。
我们推出了约12倍更快的专家混合 (MoE) 大模型训练,伴随 >减少35%的显存消耗 和 约6倍更长的上下文 通过我们新的 MoE Triton 内核和新的数学优化,且精度无损。
gpt-oss-20b 在 12.8 GB 显存下微调。Qwen3-30B-A3B(16 位 LoRA)使用 63GB。
我们的内核可在数据中心级别(B200、H100)、 消费级 以及较旧的 GPU(例如 RTX 3090)上运行,并支持 FFT、LoRA 和 QLoRA。
我们与 🤗Hugging Face 合作,使所有 MoE 训练运行使用 PyTorch 的新功能标准化, torch._grouped_mm 函数。Transformers v5 最近在 MoE 上比 v4 优化了约6倍的速度,而 Unsloth 通过自定义的 Triton grouped‑GEMM + LoRA 内核在此基础上进一步提升,带来 额外的 约2倍的加速,>35% 的显存减少以及 >6 倍更长的上下文(相较于 v4 总体加速 12-30 倍)。
试试我们的 Unsloth 笔记本以获得快速的 MoE 训练:

🦥 Unsloth MoE Triton 内核
除此之外, torch._grouped_mm (参见 Faster MoE Training),我们创建了定制的 Triton MoE 内核,在某些情况下性能更好。它们也能 向后兼容 例如 A100 这样的较旧硬件以及较旧的 PyTorch 版本。
在 A100 上,我们的 Triton 内核约快 2.5× 比起 torch._grouped_mm。这些内核还有一次性自动调优步骤来选择最佳内核配置。
自动调优在训练开始时大约需要 ~2 分钟,但在 A100 上相比 _grouped_mm可以将整个运行速度提升约 35%,对于较长的运行很值得。

模型越大、使用的上下文越多, 我们的 Unsloth 内核带来的内存节省就越明显, (效率将呈指数级扩展)。
🧭 自动后端选择
我们的主要创新是我们的 Split LoRA 方法 用于高效的 MoE,相较于 Transformers v5 + torch._grouped_mm,该方法使用约 35% 更少内存且训练速度快 2 倍。 torch._grouped_mm 定制的

+ 我们的 Triton 内核比 Transformers v4 快约 12-30 倍。 4 位 目前不建议在 QLoRA 中训练 MoE,因为 BitsandBytes 不支持它。这并非 Unsloth 独有的问题。目前请对 LoRA 使用 bf16 或进行完整微调。
Unsloth 将根据你的硬件自动选择以下后端之一:
grouped_mm
torch._grouped_mm — 在 T4 到 B200 上可用,但为 H100 及以上优化。
unsloth_triton
Unsloth Triton 内核 — 在 A100 上会自动启用,也适用于较旧的 PyTorch 版本。
native_torch
原生 PyTorch。它慢约 12 倍,但我们的显存减少仍然有效!
你也可以自己切换它们:
要启用更快的 MoE 训练,通过更新 Unsloth: pip install --upgrade unsloth unsloth_zoo
❓什么是 torch._grouped_mm?
此前,专家混合(MoE)的权重通常作为一个 ModuleList 由各专家的线性层组成。运行前向传播的唯一实际方法是对专家进行循环,这既昂贵又非最优。
PyTorch 最近引入了 grouped_mm 以解决这一确切瓶颈。与此同时,我们提供了自己的针对 MoE 优化的 Triton 内核。这也与 Transformers 的一个关键变化相一致:从 Transformers v5 起,专家权重被存储为一个 单个 nn.Parameter,使得 grouped_mm 天然适配更快的 MoE 训练和推理。
因此, transformers 4.57.6 的写法变更为:
改为 transformers 5.0.0 的风格:
torch._grouped_mm 在从 NVIDIA T4 起的 GPU 上可用,我们已在 H100、A100、B200 和 RTX 6000 Pro 上验证过,因此支持面广泛可用。
我们还此前为 gpt-oss 引入了 Unsloth 的 Flex Attention ,这些优化应使其更高效。
📊 内核结果与基准测试
下面是在不同序列长度下与已使用 torch._grouped_mm 作为 MoE 的 Transformers v5 相比的训练速度和内存使用比较。对于 gpt-oss BF16 MoE 训练,我们在 NVIDIA B200 上看到 7 倍更快的训练和 36% 的显存减少, 对于 Qwen3-30B-A3B,其速度提升为 1.8 倍,且 GLM 4.7 Flash 在 RTX PRO 6000 上速度提升 2.1 倍,。所有基准测试均在 LoRA rank = 64 且所有 MoE 层(gate、up、down)上启用 LoRA 模块的情况下完成。
gpt-oss 基准测试
我们对 unsloth/gpt-oss-20b-BF16 进行了微调以做基准测试。Unsloth 在 16K 上下文长度时快 7 倍并使用 36% 更少显存。Transformers v5 + TRL 在此场景会出现内存溢出(OOM),而 Unsloth 不会。此外,由于我们的 Long Context gpt-oss和我们的 MoE 内核,随着序列长度增加加速效果也会增加。


1024
275.35
376.99
40.91
43.88
1.4 倍
6.76%
2048
292.88
696.57
41.83
44.93
2.4 倍
6.89%
4096
370.30
1785.89
43.68
49.86
4.8 倍
12.39%
8192
712.33
5226.86
47.43
73.80
7.3 倍
35.73%
16384
1775.80
内存溢出(OOM)
55.13
内存溢出(OOM)
不适用(N/A)
不适用(N/A)
Qwen3 基准测试
在一块 NVIDIA B200上,我们看到 Qwen3-30B-A3B LoRA 大约 1.7 倍的加速和约 35% 更好的内存效率,在更长的序列长度下内存节省会进一步提升。
令人惊讶的是,Qwen3-Next 和 Coder 在 bf16 LoRA 下可以放入单块 B200 GPU。

在 H100 GPU 上,我们的表现显著优于基线,在训练中可达到最高 1.77 倍的加速, 在 4K 上下文长度微调时还能节省约 5.3GB。虽然我们可无缝扩展到 8192 的上下文长度,但 Transformers v5 + TRL 在 8K 时会 OOM。注意我们在 8K 时使用的内存比基线在 4K 时还少,因此我们可以继续推动更长的上下文长度。
1024
366.3
628.3
80.88
104.80
1.7 倍
2.06%
2048
467.0
745.3
80.88
104.81
1.6 倍
2.57%
4096
711.6
975.5
80.89
104.80
1.4 倍
5.08%
8192
1376.6
1633.5
80.90
104.81
1.2 倍
9.17%
16384
3182.2
3407.9
85.53
116.61
1.1 倍
15.26%
GLM 4.7 基准测试
Unsloth 在 GLM 4.7 Flash 上实现了 2.6 倍的吞吐量提升且显存减少 >15% 针对所有批次大小。GLM 4.7 Flash 是一个 30B 的 MoE(3B 活跃参数)具代理和编码能力的模型,采用与 DeepSeek MoE 风格类似的配置,具有 64 个路由专家和 1 个共享专家。我们将 Unsloth 的 MoE 训练与新优化的 Transformers v5 进行了基准比较。
使用下面我们的新 Colab 笔记本运行 GLM 4.7 Flash:

512
1145.0
2992.1
57.81
60.89
2.6 倍
6.51%
1024
1298.9
3323.3
58.76
62.55
2.6 倍
6.22%
2048
1831.9
4119.3
60.09
67.32
2.3 倍
9.46%
4096
2883.9
5646.1
63.34
76.78
2 倍
14.83%
⚡更快的 LoRA MoE 训练
在 Transformers/PEFT 中,常见做法是先将 LoRA 适配器合并到基础权重, 然后再执行 MoE 计算(尤其是因为 MoE 常常使用 nn.Parameter 而不是 nn.Linear )。问题是这种合并会有效地物化 LoRA 的增量(针对所有专家) lora_B @ lora_A.t ,这会非常占用内存 Unsloth 避免了这一点。我们此前用相同思路优化了通用的 LoRA 训练和推理,现在已将其应用于.
MoE + LoRA 。数学上是相同的,因此损失、梯度和输出保持不变。唯一的改变是 操作顺序 ,这是通过矩阵乘法的结合律实现的。通过这种重排,我们获得了大幅的加速和显存减少。这些优化在使用 Unsloth 训练 MoE 模型时默认
+ 我们的 Triton 内核比 Transformers v4 快约 12-30 倍。 4 位 目前不建议在 QLoRA 中训练 MoE,因为 BitsandBytes 不支持它。这并非 Unsloth 独有的问题。目前请对 LoRA 使用 bf16 或进行完整微调。
启用 (尤其是 Qwen-3 MoE、gpt-oss 和上文提到的模型)。你可以通过 UNSLOTH_MOE_BACKEND 环境变量切换实现:可选为 Triton 内核 torch._grouped_mm 或一个 基础的 PyTorch for-loop ,取决于兼容性与偏好。我们默认使用以获得最佳性能和广泛支持。 grouped_mm # 如果你想选择不同的后端(默认 grouped_mm),请设置以下变量:
LoRA 是一种参数高效的微调方法:你不是更新完整的权重矩阵,而是训练一个低秩的“适配器”,参数远少,从而大幅减少优化器的内存需求。
如果原始权重的形状为
(m, n) ,LoRA 添加两个可训练矩阵,其形状为(m, r) (r, n) 和 。它们的乘积为,但你只为以下项跟踪优化器状态和梯度: ,LoRA 添加两个可训练矩阵,其形状为m*r + r*n
参数(LoRA),而不是m*n参数(完整微调)。关于对 MoE 的微调——不建议微调路由器层,因此我们默认将其禁用。
对于典型的 MLP 层,
m ≈ 4096,n ≈ 12k,r ≈ 64 ,大约为~1M 的 LoRA 参数 vs ~48M 的完整参数 — 大约 通常几乎没有或没有准确率损失。 ~2%, MoE 下 LoRA 的情况有所不同
MoE 层不同在于你有
E 个专家 MLP 并行存在, 因此任何逐专家的更改(例如添加 LoRA)会在所有专家上扩展。以
Qwen3‑30B‑A3B 为例:隐藏维度m=2048 ,中间维度n=768 ,E=128, 专家且每个 token 激活 k=8 。每个专家: gate_proj
up_proj和(m, n) = (2048, 768):down_proj(n, m) = (768, 2048):在
LoRA 秩 r=64 下,每个投影增加r*(m+n)=64*(2048+768)=180,224 每专家的参数(约为 一个 11% 2048×768 矩阵 的一部分)。核心问题是, r/n = 64/768 相对于典型的 MLP 配置而言很大,例如, r/n = 64/25600 在 Qwen3-32B 中为类似规模。 如果你在所有
专家上将其物化,内存会迅速增加。并且由于 通常会被融合为 gate_up_proj up_proj 和 (m, n) = (2048, 768) ,你通常会把两者一起物化,导致开销/峰值内存大致翻倍。 在内存方面,对于序列长度 s、E 个专家和选择的k
,两种方法共有以下常见项: # 所有这些值均为每个专家的量 最终输出:(s, n)
对于 Unsloth 的 Split LoRA 方法,我们执行以下操作:
Y @ loraB: (s, r) @ (r, n) # 同样对 k 个专家是稀疏的 = k s n 参数
把这些值代入,我们得到
s < 32K。 在计算量方面,对于序列长度 s
、E 个专家和选择的前, k ,我们正在执行: # 所有这些值均为每个专家的量 在我们提到的 Unsloth split lora 情况下,我们有:
从分析的角度看,Split LoRA 更优的临界点是当
s > E m n / [k (m+n)] 时, 这大约是 16K token,对于 Qwen3-30B-A3B 风格的模型。
最后,部分加速来自于 减少的内存传输:现代 GPU 常常是 带宽受限的,因此传输更少的数据比 FLOPs 更重要。一个粗略的加速估计为 E m n / [k·s·(m+n)],所以它强烈依赖于 s、E、k以及矩阵形状。
🔮 模型支持
Unsloth 支持 Qwen、gpt-oss、DeepSeek 和 GLM 模型的更快 MoE 训练:
Qwen3 (Thinking 和 Instruct):VL • 2507 • Coder
gpt-oss:20B • 120B • safeguard
GLM:4.5 • 4.6 • 4.6-Air • 4.7 • 4.7-Flash
DeepSeek:V3 • R1 • V3.1 • V3.2
我们可能还没上传某些 MoE 模型,但 Unsloth 仍应支持它们。
📈 更多基准测试
gpt-oss BF16 基准
训练速度(含与 Transformers v4 的比较)
1024
275.35
376.99
2111.18
1.37 倍
2048
292.88
696.57
2626.80
2.38 倍
4096
370.30
1785.89
4027.93
4.82 倍
8192
712.33
5226.86
8513.52
7.34 倍
16384
1775.80
内存溢出(OOM)
内存溢出(OOM)
不适用(N/A)
显存使用(VRAM)
1024
40.91
43.88
89.75
6.76%
2048
41.83
44.93
90.47
6.89%
4096
43.68
49.86
92.72
12.39%
8192
47.43
73.80
100.3
35.73%
16384
55.13
内存溢出(OOM)
内存溢出(OOM)
不适用(N/A)
🎉 重要的 Unsloth 更新
作为我们 MoE 发布的一部分,我们还做了 Gemma-3 现在默认使用 Flex-Attention, 并且这在 float16 设置下也可工作(之前存在的无穷问题我们已解决)。 Gemma-3 现在使用 O(N) 内存而非 O(N^2),训练速度提高 >3 倍 (随上下文长度扩展时表现更好)。先前的 Unsloth 版本会出现 OOM。

1K
20.1 GB
20.1 GB
0 GB(0%)
2K
21.5 GB
21.1 GB
0.3 GB(2%)
4K
27.7 GB
23.3 GB
4.5 GB(16%)
8K
52.3 GB
27.5 GB
24.8 GB(47%)
16K
内存溢出(OOM)
36.0 GB
--
24K
内存溢出(OOM)
44.6 GB
--
32K
内存溢出(OOM)
53.1 GB
--
48K
内存溢出(OOM)
38.4 GB
--
64K
内存溢出(OOM)
44.7 GB
--
视觉微调现在接受仅包含图像和文本混合的数据!
trl==0.27.1和transformers==5.1.0得到较好支持 — 之前覆盖了我们 120 个笔记本的 30%,现在覆盖率已超过 80% — 我们计划在接下来的几天内做到 100%。许多 bug 修复和其他更新 — 参见 https://github.com/unslothai/unsloth/releases/tag/February-2026
要启用更快的 MoE 训练,通过更新 Unsloth: pip install --upgrade unsloth unsloth_zoo
致谢
我们感谢 Hugging Face 团队与我们合作,为社区改进 MoE 训练。
我们也由衷感谢 torchao 团队,特别是 Vasily Kuznetsov (vkuzo),感谢他帮助我们使 grouped_mm 支持 float16,以便在 T4 上工作并与 A100 保持向后兼容。
最后更新于
这有帮助吗?

