使用 Unsloth 内核 + 打包实现 3 倍更快的 LLM 训练

了解 Unsloth 如何提高训练吞吐量并消除微调时的填充浪费。

Unsloth 现在支持最多 5× 更快 (通常为 3x)使用我们新的自定义进行训练 RoPE 和 MLP Triton 内核,以及我们新的智能自动打包。Unsloth 的新内核 + 功能不仅提高了训练速度,而且进一步 减少 VRAM 使用(30% - 90%) 且没有精度损失。 Unsloth GitHubarrow-up-right 这意味着您现在可以在诸如 Qwen3-4B 这样的 LLM 上训练,不仅仅在 3GB VRAM上,而且速度提高 3 倍。

我们的自动 无填充 未污染打包会在所有训练运行中智能启用,无需任何更改,并适用于所有快速注意力后端(FlashAttention 3、xFormers、SDPA)。 基准测试 显示训练损失与未打包运行 完全相同.

  • 2.3x 更快的 QK 旋转嵌入(RoPE) 带有打包支持的融合 Triton 内核

  • 更新的 SwiGLU、GeGLU 内核,带有 用于长上下文的 int64 索引

  • 2.5x 到 5x 更快的未污染打包 支持 xformers、SDPA、FA3 后端

  • 2.1x 更快的无填充,VRAM 减少 50%,准确度变化 0%

  • Unsloth 现在还具有改进的 SFT 损失稳定性和更可预测的 GPU 利用率。

  • 此新升级适用于 所有训练方法 例如全量微调、预训练等。

🥁带有打包的融合 QK RoPE Triton 内核

早在 2023 年 12 月,我们在 Unsloth 发布时引入了用 Triton 编写的 RoPE 内核。2024 年 3 月,社区成员通过优化 RoPE 内核以允许为一组头启动一个块,使端到端训练提高了 1-2%。参见 PR 238arrow-up-right.

一个问题是对于每个 Q 和 K,有 2 个 Triton 内核。我们现在将它们合并为 1 个 Triton 内核,并 启用了可变长度 RoPE,这对于无填充和打包支持是必要的。这使得微基准中的 RoPE 内核 在较长上下文长度上快 2.3x,在较短上下文长度上快 1.9x。

我们还消除了所有克隆和连续转置操作,因此 RoPE 现在完全就地执行,进一步减少了 GPU 内存。注意在反向传播中,我们看到 sin1 = -sin1 因为:

🚃Triton 内核的 Int64 索引

在我们引入的 500K 长上下文训练期间, 500K Context Training我们会遇到 CUDA 越界错误。这是因为 SwiGLU、GeGLU 的 MLP 内核使用了 Triton 和 CUDA 中默认的 int32 索引。

我们不能只是做 tl.program_id(0).to(tl.int64) 因为由于 int64 索引,训练会略微变慢。我们改为将其做为 LONG_INDEXING: tl.constexpr 变量,以便 Triton 编译器可以对其进行特化。这允许短上下文和长上下文运行都表现良好!

🧮为什么需要填充及数学加速原理

计算机和 GPU 无法处理不同长度的数据集,因此我们必须用 0 填充它们。这会造成浪费。假设我们有一个数据集,其中 50% 是短序列 S,50% 是长序列 L,那么在最坏情况下,填充会导致令牌使用量为 batchsize×L\text{batchsize} \times L 因为最长序列长度占主导。

通过将多个示例打包到一个长的一维张量中,我们可以消除大量填充。实际上我们得到以下令牌使用:

Token Usage=batchsize2L+batchsize2S\text{Token Usage} = \frac{\text{batchsize}}{2}L+\frac{\text{batchsize}}{2}S

通过一些数学和代数,我们可以算出加速比为:

Speedup=batchsize×Lbatchsize2L+batchsize2S=2LL+S\text{Speedup} = \frac{\text{batchsize} \times L}{\frac{\text{batchsize}}{2}L+\frac{\text{batchsize}}{2}S} = 2 \frac{L}{L + S}

通过假设 S0S\rightarrow0 我们得到理论上 2 倍的加速,因为 2LL+0=22 \frac{L}{L + 0} = 2

通过改变 50% 短序列的比例,并假设我们有更多短序列,例如 20% 长序列和 80% 短序列,我们得到 L0.2L+0.8SL0.2L=5\frac{L}{0.2L + 0.8S}\rightarrow\frac{L}{0.2L}=5 因此训练速度提高 5 倍!这意味着打包的加速取决于数据集中短行的多少(越多越短,速度越快)。

🎬默认无填充

除了在设置时可获得的大吞吐量提升外, packing = True 在您的 SFTConfig ,我们将 中自动使用无填充批处理 以减少填充浪费、提高吞吐量并增加每秒令牌数,同时导致 完全相同的损失 就像在 Unsloth 之前的版本中看到的一样。

例如对于 Qwen3-8B 和 Qwen3-32B,我们看到内存使用减少 60%,速度提升 2 倍,并且具有完全相同的损失和梯度范数曲线!

♠️未污染打包 2-5x 更快的训练

真实数据集可能包含不同的序列长度,因此将批量大小增加到例如 32 会导致填充,使训练变慢并使用更多 VRAM。

circle-check

当我们将多个样本打包到一个一维张量中时,我们会保留序列长度元数据以便正确掩蔽样本,且不会在样本之间泄漏注意力。我们还需要在 New 3x Faster Training 中描述的 RoPE 内核以允许重置位置 id。

4 个示例未打包会浪费空间

未污染打包创建正确的注意力模式

通过改变 50% 短序列的比例,并假设我们有更多短序列,例如 20% 长序列和 80% 短序列,我们得到 L0.2L+0.8SL0.2L=5\frac{L}{0.2L + 0.8S}\rightarrow\frac{L}{0.2L}=5 因此训练速度提高 5 倍!这意味着打包的加速取决于数据集中短行的多少(越多越短,速度越快)。

🏖️分析与基准

为了演示在使用我们新的内核和打包数据进行训练时的各种改进,我们在以下模型上进行了微调运行: Qwen3-32B、Qwen3-8B、Llama 3 8B 在 yahma/alpaca-cleaned 数据集上并测量了各种 训练损失 吞吐量和效率指标。我们将我们的新运行与一个启用了我们自己的内核/优化和像 Flash Attention 3 (FA3) 这类内核的标准优化训练运行进行了比较。我们固定了 max_length = 1024 并在 {1, 2, 4, 8, 16, 32} 中改变批量大小。这允许每批的最大令牌数在 {1024, 2048, 4096, 8192, 16K, 32K} 中变化。

以上显示了新的 Unsloth 在不同批量大小下令牌每秒(tokens/s)训练吞吐量的变化。这转化为在您的数据集上训练一个 epoch 快 1.7-3x(有时甚至 5x 或更多)!如果您的数据中有许多短序列且训练运行较长,这些收益会更显著,正如在 New 3x Faster Training

中所述。

上述显示了每批平均有效令牌(即非填充)的百分比。随着批量大小的增加,未打包情况下会看到更多填充令牌,而在已打包情况下,我们无论最大序列长度如何都能实现高打包效率。

请注意,由于批处理逻辑会将批次剪裁为批次中看到的最大序列长度,当批量大小为 1 时,未打包数据全部是有效令牌(即无填充)。然而,随着更多示例被加入批次,平均填充增加,在批量大小为 8 时几乎达到 50% 的填充!我们的样本打包实现消除了这种浪费。 yahma/alpaca-cleaned 第一张图(上方)绘制了 max_length = 2048 时,Unsloth 新的带打包 + 内核(栗色)与 Unsloth 旧版本(灰色)的比较。两者都以max_steps = 500

训练,但我们在 x 轴上以实时时钟时间绘图。注意在相同步数(并且只多用一点点实时时钟时间)下,已打包情况下我们训练了接近 40% 的一个 epoch,而未打包情况下不到 5%。

类似地,第 2 张图(上方)绘制了相同运行的损失,这次在 x 轴上以训练步数绘制。注意损失在尺度和趋势上匹配,但打包情况下损失波动更小,因为模型在每个训练步看到更多令牌。

如何启用打包?先更新 Unsloth,默认已启用无填充

pip install --upgrade --force-reinstall --no-cache-dir --no-deps unsloth_zoo 我们还通过 Xformers 支持 Flash Attention 3、支持 SDPA、Flash Attention 2,这在旧 GPU(Tesla T4、RTX 2080)和新 GPU(如 H100、B200 等)上都能工作!样本打包工作不受注意力后端或模型家族选择的影响

,因此尽享之前这些快速注意力实现所带来的相同加速! packing = True 如果您想显式启用打包,则添加

circle-exclamation

trainer.train() Unsloth 笔记本

我们所有的笔记本都自动更快(无需任何操作)。参见

Llama 3.1 对话 更快: 500K Context Training 谢谢!如果您感兴趣,请参阅我们的 内存高效 RL 博客, Long Context gpt-oss 博客和

最后更新于

这有帮助吗?