For the complete documentation index, see llms.txt. This page is also available as Markdown.

内存高效 RL

我们很高兴在 Unsloth 中推出更高效的强化学习(RL),并带来多项算法改进:

  • 上下文长度提升 1.2 到 1.7 倍 没有任何变慢,也不会额外占用内存!

  • RL 训练运行速度提升 10% 采用了改进后的内核和异步数据搬运

  • 快 2 倍 torch.compile 在模型加载期间

Unsloth 已经 在 FA2 的所有其他方案中,已能提升 RL 训练速度、上下文窗口,并将 VRAM 占用降低 50–90%,但现在 Unsloth 的待机模式 进一步提升了这一点。我们的待机功能相较于其他实现,能独特地限制速度下降,有时甚至还能让训练更快!

现在,Qwen3-32B LoRA 16 位可以达到 6,144 的上下文长度,而之前在 1xH100 80GB GPU 上只有 3,600(更长 1.7 倍)。Llama-3.1-8B QLoRA 4bit 可以达到 47,500 的长度,而之前是 42,000(更长 1.13 倍)。

我们通过多种内核优化,使 RL 运行速度提升了 10%,并在从训练切换到推理模式时移除了 CPU 与 GPU 之间的 LoRA 通信通道。最后,我们使用了自定义 torch.compile 标志,使 vLLM 的 rollout 速度提升了 10%,并将编译时间缩短了 2 倍。

如何启用优化

要启用 Unsloth 的待机模式 功能,设置环境变量 UNSLOTH_VLLM_STANDBY 在任何 Unsloth 导入之前。然后设置 gpu_memory_utilization = 0.95 就可以了!

import os
os.environ["UNSLOTH_VLLM_STANDBY"] = "1"

from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Qwen3-8B-Base",
    max_seq_length = 2048, # 可为更长的推理轨迹增加
    load_in_4bit = False, # LoRA 16bit 时为 False
    fast_inference = True,
    max_lora_rank = 32, # rank 越大 = 越聪明,但越慢
    gpu_memory_utilization = 0.95,
)

🎓不再需要 gpu_memory_utilization!

有了 Unsloth 新的 RL 改进,你再也不用担心调节或设置 gpu_memory_utilization 了——只需把 GPU 利用率设为 90% 或 95% 即可——遗憾的是 100% 不行,因为小张量需要一些空间。以前需要在 30% 到 95% 之间调试——现在不用了!直接设到最大,剩下的交给 Unsloth!

⁉️为什么 RL 会占用这么多内存?

GRPO(以及许多 RL 变体)高度依赖生成,而生成主要由 vLLM 提供支持。但这带来了很高的代价,因为它需要持续的 GPU 显存来存放权重、激活值和 KV Cache.

推理会消耗大量 VRAM

而训练同样也会使用 VRAM!

这意味着 RL 需要同时在 GPU 上保留 2 套 VRAM / 内存:

  1. 推理引擎(有模型权重、KV cache)

  2. 训练引擎(有模型权重、激活值、梯度、优化器状态)

当前的 RL 框架在 80GB GPU 上必须 50/50 分配,50% 给推理,50% 给训练。而且把权重从训练模式移动到推理模式可能要花相当长时间。

80GB GPU
推理引擎(50%)
训练引擎(50%)

模型权重

16GB

16GB

KV Cache

24GB

激活值、梯度、优化器状态

24GB

之前的 Unsloth 版本已经在智能地优化上述内容,因为我们 直接共享 vLLM 的权重空间,从而消除了模型权重的双重内存占用。例如这会释放 16GB 空间,可用于增加上下文长度或提升生成速度。另外,我们不需要进行内存搬运,因此训练更快。

80GB GPU
推理引擎(50%)
训练引擎(50%)

模型权重

共享 16GB

<<< 共享

KV Cache

24GB + 8GB= 32GB

激活值、梯度、优化器状态

24GB + 8GB=32GB

🦥Unsloth 待机模式

但我们还能更进一步——首先要注意,RL 的流程是推理,然后训练,再推理,再训练,等等。

这意味着推理和训练的内存空间理论上可以复用,因为推理和训练是分离的模式——这就是 vLLM 的睡眠模式功能 的作用,它有 2 个选项:

  1. level = 1 将权重复制到 CPU 并删除 KV cache

  2. level = 2 删除权重并删除 KV cache

但要提醒的是,在 Unsloth 中我们共享 vLLM 的权重内存空间——这意味着我们需要一种新的方式来删除 KV cache,并忽略删除权重的操作,我们把这称为 Unsloth 待机模式。

80GB GPU
推理引擎
训练引擎

模型权重

共享 16GB

<<< 共享

多用途

64GB 空间

KV Cache

激活值、梯度、优化器状态

要启用此功能,只需在任何 Unsloth 导入之前,将下面内容添加到所有 RL / GRPO 训练运行中:

🧪性能实验

在这里你会看到我们如何对 GRPO 的内存使用和上下文长度进行基准测试。请注意,我们会 每个 prompt 生成 2 次,因为 GRPO 要工作,至少需要 2 次生成来计算样本均值和方差。 没有 2 次生成时,单个样本的标准差为 0。这会导致使用该公式的优势值:(reward - mean)/std 变为未定义.

Z=riμ1n(riμ)2Zn=1=r1μ11(r1μ)2=00=undefinedZ=\frac{r_i - \mu}{\sqrt{\frac{1}{n}\sum(r_i-\mu)^2}} \\ Z_{n=1}=\frac{r_1 - \mu}{\sqrt{\frac{1}{1}\sum(r_1-\mu)^2}}=\frac{0}{0}=\text{undefined}

这意味着就 GRPO 而言,Qwen-3 32B 的最大上下文长度 6,144 实际上是 6,144 乘以 2 次生成,即长度 12,288。

我们下面提供了 Llama-3.1 8B 在 LoRA(16bit)和 QLoRA(4bit)上的实验:

如果你注意到任何训练时间差异,其实并不大。在我们的同类对比中,我们观察到训练时间下降不到 1%,甚至有时会加速,这可以归因于误差范围。

我们还推测,由于内存压力降低,速度提升也是可能的,因此在 CUDA 内存分配器一侧,可能需要更少的内存清理。

在上图中,你可以看到单张 T4 GPU 上 Qwen 3 4B 的基线模式与待机模式之间的差异。 我们可以把 vllm 的 gpu_memory_utilisation 提高到 0.95 这么高,而不必担心它会影响训练。这意味着你可以容纳更长上下文的序列,并处理更多序列。例如,在第一种情况下,我们有足够内存容纳并处理 32K 长度的序列,前提是训练允许;而之前,任何长度超过 2K 的输入都可能无法装入,最终导致 OOM(显存不足)。

实验
配置
状态
GPU 内存使用
备注

待机 True

vllm_gpu_util 0.95

num_gen 2

grad_acc_steps 2

运行 40 步 / 40 分钟

14.5 GiB(由 vllm_gpu_util 设置)

足以容纳 32K KVCache,分块大小为 2-4K,或者说 16K KVCache + 16K 分块

待机 True

vllm_gpu_util 0.9

num_gen 2

grad_acc_steps 2

40 分钟内运行 32 步

13.8 GiB(由…设置)

大致足以容纳约 28K KVCache,分块大小为 2-4K,或者说 15K KVCache + 15K 分块

待机 False

vllm_gpu_util 0.9

num_gen 2

grad_acc_steps 2

模型能加载,但无法训练,因为连 batch size 为 1 都放不下

OOM

待机 False

vllm_gpu_util 0.8

num_gen 2

grad_acc_steps 2

模型能加载,但无法训练,因为连 batch size 为 1 都放不下

OOM

待机 False

vllm_gpu_util 0.7

num_gen 2

grad_acc_steps 2

训练正常

28 步需要 39 分钟

约 15.1GiB

任何稍长一些的输入都会在 colab 上导致 OOM

待机 True

vllm_gpu_util 0.7

num_gen 2

grad_acc_steps 2

训练正常

29 步需要 40 分钟

13GiB,但大多数时候在 10-11GB 左右

在相同配置下,我们这里节省了 2GiB,即 15% 的内存。对于更长的序列,这个数值还可以更高

H100 实验

模型
GPU
序列长度
生成次数
梯度累积步数

Qwen2.5-14B-Instruct

NVIDIA H100 80GB PCIe

32,768

8

4

在下面可折叠的结果中,你可以看到峰值内存使用相差 9GiB(注意,在我们的案例中,90% 的时间里,GPU 内存使用量与峰值内存相同)。 从直观上看,使用 TRL 和 LoRA,我们最多只能微调一个 80 亿参数模型,且上下文长度最多 1024(少 32 倍)。 任何更长的序列长度(在相似配置下)都会导致进程因 OOM 而失败。

点击查看 Unsloth 待机模式 vs. 无待机基准测试

下图展示了在 Unsloth 中,待机模式与非待机训练的对比。结果已对 3 次运行取平均,以确保指标没有噪声。事实上,如果你足够放大,会发现启用待机模式也会让它更快,这很可能还是因为前面提到的内存压力更小。

此前的 A100 40GB 实验

在我们此前对 A100 40GB GPU、使用 Qwen-2.5-3b-instruct 且每个样本 8 次生成的实验中,我们观察到:没有待机模式时,GRPO 训练(模型以 16bit 加载,LoRA,仅权重可训练)最多只能放下 6K 序列长度。使用待机功能后,我们可以放下 10K 甚至更高! 相比之下,TRL 在保持相同 batch size 的情况下,只能提供最多 1K 的上下文长度。

🎉其他优化

我们现在选择了更好的编译标志,并将编译时间缩短了 50% 或更多。我们还成功地动态补丁任意 vLLM 版本以处理 gc.collect 更好,以实现向后兼容,灵感来自这个 vLLM pull request。这将编译时间从 2 分钟缩短到 40 秒以内。

我们还优化了 torch.compile 标志,并尝试开启一些标志——不幸的是 combo_kernels 以及 multi_kernel 在 vLLM 0.10 和 Torch 2.8/2.9 nightly 上无法正常工作,并且 coordinate_descent_tuning 让所有内核的自动调优速度大幅变慢。它以前的编译时间不到一分钟,但开启后却要 13 分钟以上,而且性能提升很小。

📚GRPO 笔记本

我们所有的 GRPO 笔记本默认都启用了 Unsloth 待机模式和所有优化!请查看 https://docs.unsloth.ai/get-started/unsloth-notebooks 以获取我们全部的 GRPO 笔记本,或者试试下面这些:

最后更新于

这有帮助吗?