💎使用 Unsloth 将 MoE 模型微调速度提高 12 倍
使用 Unsloth 在本地训练 MoE LLM 指南。
我们推出了约 12 倍更快的专家混合 (MoE) 大语言模型训练,配合 >35% 更少的显存 以及 约 6 倍更长的上下文 通过我们新的 MoE Triton 内核和新的数学优化,且在准确性上没有损失。
gpt-oss-20b 在 12.8 GB 显存下进行微调。
我们的内核可在数据中心(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 + 比较时大约使用 ~35% 更少的内存并且训练速度快 2 倍。 torch._grouped_mm自定义 torch._grouped_mm + 我们的 Triton 内核比 Transformers v4 快约 12-30 倍。

在 4 位 下训练 MoE 模型目前不建议使用 QLoRA,因为 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 这些优化应使其更高效。
📊 内核结果与基准测试
下面是与 Transformers v5(已为 MoE 使用 torch._grouped_mm )相比的不同序列长度下训练速度和内存使用的对比。对于 gpt-oss BF16 MoE 训练,我们在 NVIDIA B200 上看到 7 倍的训练速度提升和 36% 的显存减少 。对于 Qwen3-30B-A3B,则为 1.8 倍的加速,且 GLM 4.7 Flash 在 RTX PRO 6000 上加速 2.1 倍。所有基准测试均在 LoRA 秩 = 64 且所有 MoE 层(gate、up、down)上启用 LoRA 模块的情况下进行。
gpt-oss 基准
我们微调了 unsloth/gpt-oss-20b-BF16 用于基准测试。在 16K 上下文长度时,Unsloth 速度快 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
内存溢出
55.13
内存溢出
不适用
不适用
Qwen3 基准
在 NVIDIA B200上,我们观察到 在 Qwen3-30B-A3B LoRA 上约 1.7 倍的加速和约 35% 更好的内存效率,而在更长的序列长度下内存节省会进一步改善。
Qwen3-Coder-Next 出人意料地在单个 B200 GPU 上以 bf16 LoRA 方式适配。

在 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 实现了 2.6 倍更高的吞吐量并减少 >15% 的显存 在所有批次大小下针对 GLM 4.7 Flash。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 。数学是相同的,因此损失、梯度和输出保持不变。唯一的变化是 运算顺序,这是通过矩阵乘法的结合性实现的。通过这种重新排序,我们获得了显著的加速和内存减少。
在 4 位 下训练 MoE 模型目前不建议使用 QLoRA,因为 BitsandBytes 尚不支持。这并不是 Unsloth 特有的问题。目前,请为 LoRA 使用 bf16 或进行完整微调。
这些优化在使用 Unsloth 训练 MoE 模型时默认 启用 (特别是 Qwen-3 MoE、gpt-oss 以及上文提到的模型)。你可以通过 UNSLOTH_MOE_BACKEND 环境变量切换实现:要么使用 torch._grouped_mm Triton 内核 要么使用 基本的 PyTorch for 循环,取决于兼容性和偏好。我们默认使用 grouped_mm 以获得最佳性能和广泛的支持。
📚 实现细节
LoRA 是一种参数高效的微调方法:你不更新完整的权重矩阵,而是训练一个低秩的“适配器”,参数远少于完整矩阵,从而大幅减少优化器内存。
如果原始权重的形状为 (m,n),LoRA 添加了两个可训练矩阵,形状为 (m,r) 以及 (r,n)。它们的乘积是 (m,n),但你只跟踪优化器状态和梯度用于:
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 个专家, 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_proj 以及 up_proj 通常被融合为 gate_up_proj,你通常会把两者一起具体化,大致会使开销/峰值内存翻倍。
在内存方面,对于序列长度 s、E 个专家和 k 被选择,我们对两种方法都有以下常见情况
从这里开始两者会有所不同。对于 peft 的方法我们有
对于 Unsloth 的拆分 LoRA 方法,我们执行以下操作
现在以 Qwen3-30B-A3B 为例。
E = 128,k = 8,m = 2048,n = 768。 把这些都代入,我们得到 s < 32K。
在计算方面,对于序列长度 s, E 专家和前 k 被选择,我们正在做:
在我们提到的 Unsloth 拆分 lora 的情况下,我们有
从分析角度看,Split LoRA 更优的临界点是当 s > Emn/k(m+n) 这大致在以下数量级 16K 标记,对于 Qwen3-30B-A3B 风格的模型。
最后,一些加速来自于 减少的内存传输:现代 GPU 通常是 带宽受限的,所以传输更少的数据可能比 FLOPs 更重要。一个粗略的加速估计是 Emn / [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.37x
2048
292.88
696.57
2626.80
2.38x
4096
370.30
1785.89
4027.93
4.82x
8192
712.33
5226.86
8513.52
7.34x
16384
1775.80
内存溢出
内存溢出
不适用
内存 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
内存溢出
内存溢出
不适用
🎉 重要的 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
内存溢出
36.0 GB
--
24K
内存溢出
44.6 GB
--
32K
内存溢出
53.1 GB
--
48K
内存溢出
38.4 GB
--
64K
内存溢出
44.7 GB
--
视觉微调现在接受仅图像与文本混合的数据!
trl==0.27.1以及transformers==5.1.0得到良好支持——之前覆盖了我们 120 个笔记本中的 30%,但现在我们覆盖 >80%——我们计划在接下来的几天内将其提升到 100%。许多错误修复和其他更新——参见 https://github.com/unslothai/unsloth/releases/tag/February-2026
要启用更快的 MoE 训练,请通过以下方式更新 Unsloth: pip install --upgrade unsloth unsloth_zoo
致谢
我们感谢 Hugging Face 团队与我们合作,以改进社区的 MoE 训练。
我们还由衷感谢 torchao 团队,特别是 Vasily Kuznetsov(vkuzo)帮助我们启用 float16 的 grouped_mm 支持以便在 T4 上工作并与 A100 保持向后兼容。
最后更新于
这有帮助吗?

