SGLang 后端

最后更新时间:2025 年 5 月 31 日。

作者:SGLang RL Team,按姓氏字母顺序排列

Jingyi ChenYitong GuanZhuobin HuangJiajun LiJi LiShenggui LiJunrong LinXiang LongRui LuJin PanShuai ShiYushen SuXinyuan TongChendong WangHanchen ZhangHaoran WangYongan XiangChengxing XieYuhao YangJinwei YaoQiaolin YuYuzhen ZhouChenyang Zhao

简介

SGLang 是一个开源的、最先进的推理服务引擎,已被 xAI 完全采用,以支持 Grok 在研究和部署过程中的所有推理需求。

目前,verl 在部署阶段完全支持使用 SGLang 作为推理引擎。作为部署引擎,SGLang 提供了与 vLLM 相同的功能覆盖,包括内存节省和多节点部署功能。安装 verl 和 SGLang 后,只需在启动脚本中添加 actor_rollout_ref.rollout.name=sglang 即可在两个推理框架之间无缝切换。

此外,SGLang 团队还在积极支持多轮智能体 RL、VLM RLHF、基于服务器的 RLHF 和部分部署等功能。您可以在 Roadmap 跟踪 中跟踪相关开发进展。

安装

请务必按照以下命令安装 SGLang 和 verl。

pip install --upgrade pip
# 当前版本为 0.4.8,可能会随时更新,请参考 `setup.py` 中指定的最新版本
pip install -e ".[sglang]"

您可以检查您的环境中是否已安装以下依赖项:

Note

  • PyTorch: 2.6.0+cu124

  • CUDA: 12.4

  • flashinfer-python: 0.2.5+cu124torch2.6

  • SGLang: 0.4.6.post5

  • sgl-kernel: 0.1.4

在单台机器上使用 SGLang 作为 PPO 训练的推理后端

我们使用 Qwen/Qwen2-7B-Instruct 在 gsm8k 数据集上进行简单测试。

  1. 运行以下命令准备 gsm8k 数据集:

python3 examples/data_preprocess/gsm8k.py
  1. 运行以下脚本在具有 4 个 GPU 的单台机器上进行 PPO 实验:

export SGL_DISABLE_TP_MEMORY_INBALANCE_CHECK=True
PYTHONUNBUFFERED=1 python3 -m verl.trainer.main_ppo \
    data.train_files=$HOME/data/gsm8k/train.parquet \
    data.val_files=$HOME/data/gsm8k/test.parquet \
    data.train_batch_size=4096 \
    data.max_prompt_length=4096 \
    data.max_response_length=4096 \
    actor_rollout_ref.rollout.name=sglang \
    actor_rollout_ref.model.path=Qwen/Qwen2-7B-Instruct \
    actor_rollout_ref.actor.optim.lr=1e-6 \
    actor_rollout_ref.actor.ppo_mini_batch_size=64 \
    actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=4 \
    actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=8 \
    actor_rollout_ref.model.enable_gradient_checkpointing=True \
    actor_rollout_ref.actor.fsdp_config.param_offload=True \
    actor_rollout_ref.actor.fsdp_config.optimizer_offload=True \
    actor_rollout_ref.rollout.tensor_model_parallel_size=2 \
    actor_rollout_ref.rollout.gpu_memory_utilization=0.8 \
    actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=4 \
    critic.optim.lr=1e-5 \
    critic.model.path=Qwen/Qwen2-7B-Instruct \
    critic.ppo_micro_batch_size_per_gpu=4 \
    critic.model.fsdp_config.param_offload=True \
    critic.model.fsdp_config.optimizer_offload=True \
    algorithm.kl_ctrl.kl_coef=0.001 \
    trainer.logger=console \
    trainer.val_before_train=False \
    trainer.n_gpus_per_node=4 \
    trainer.nnodes=1 \
    trainer.save_freq=-1 \
    trainer.test_freq=10 \
    trainer.total_epochs=15 2>&1 | tee verl_demo.log

为什么要导出 SGL_DISABLE_TP_MEMORY_INBALANCE_CHECK?

  1. verl 在 rollout 期间初始化 SGLangRollout 模块,用于评估/生成样本。

  2. SGLangRollout 会初始化 Engine,并进一步初始化 torch.distributed.DeviceMesh,用于支持张量并行(TP)。

  3. DeviceMesh.init() 内部会检查所有参与设备的可用 GPU 内存。如果差异过大(超过约 10%),它会直接报告错误,以避免初始化失败或死锁。

为什么会出现 GPU 内存不一致?

1. Ray 分布式 Actor 加载模型的时机不同

verl 使用基于 Ray 的多进程、多 GPU 并发训练。每个 WorkerDict 可能在不同时间被调用:

self.rollout = SGLangRollout(...)

不同的 worker 在不同时间初始化模型 → 导致内存使用量不同。

2. 延迟初始化导致内存偏差

有些 worker 比其他 worker 更早开始加载模型/进行推理(例如,generate_sequences()compute_log_prob())。 早开始的 worker 已经占用了 GPU 内存 → 后开始的 worker 仍有空闲内存 → 出现内存差异。

3. SGLang 的 TP 初始化使用“所有设备广播”,但没有统一的释放时机

尽管 SGLangRollout 可能只涉及部分 GPU,但其 Engine 初始化会调用 torch.distributed.init_process_group() 并广播权重,因此:

  • 非 rollout 的 GPU 也会加入通信。

  • 之后,DeviceMesh 初始化会因为“内存不一致”而失败。

4. 不同的 FSDP/TP 加载行为也会导致不匹配

如果使用:

actor.fsdp_config.param_offload=True
ref.fsdp_config.param_offload=True

那么一些 worker 将参数保留在 CPU 上,而其他 worker 则已将其分片到 GPU → 导致内存布局不对称。

在多台机器上使用 SGLang 作为 PPO 训练的推理后端

SGLang 也支持在 IPv4 和 IPv6 场景下运行 verl 基于 RAY 的跨机器推理。在下面的脚本中,我们使用 TP=16 进行跨机器推理。假设我们有两台互联的机器:node0 的 IP 地址是 10.94.16.4,node1 的 IP 地址是 10.94.16.5。

  1. 在 node0 上启动 Ray:

ray start --head --dashboard-host=0.0.0.0

您将看到以下提示:

Usage stats collection is enabled. To disable this, add `--disable-usage-stats` to the command that starts the cluster, or run the following command: `ray disable-usage-stats` before starting the cluster. See https://docs.ray.io/en/master/cluster/usage-stats.html for more details.

Local node IP: 10.94.16.4

--------------------
Ray runtime started.
--------------------

Next steps
To add another node to this Ray cluster, run
    ray start --address='10.94.16.4:6379'
  1. 让 node1 加入 Ray 集群:

在 node1 上运行以下命令:

ray start --address='10.94.16.4:6379'

运行以下命令确认 Ray 集群现在有两个节点:

ray status

您可以看到集群有两个节点,共 16 个 GPU:

======== Autoscaler status: 2025-04-09 09:25:37.694016 ========
Node status
---------------------------------------------------------------
Active:
 1 node_ef382ffd687d8f6b060c1b68e63ada7341b936fe5b1901dd04de1027
 1 node_1eb4d7d07e793114c23a89d1a41f1f76acf6ef5b35af844a4ee8e4ba
Pending:
 (no pending nodes)
Recent failures:
 (no failures)

Resources
---------------------------------------------------------------
Usage:
 0.0/360.0 CPU
 0.0/16.0 GPU
 0B/3.39TiB memory
 0B/372.53GiB object_store_memory
  1. 运行以下脚本,使用 TP=16 在 2 台机器上(共 16 个 GPU)训练 meta-llama/Llama-3.1-8B-Instruct:

DATA_DIR=$HOME/data/gsm8k

python3 -m verl.trainer.main_ppo \
    actor_rollout_ref.rollout.name=sglang \
    data.train_files=$DATA_DIR/train.parquet \
    data.val_files=$DATA_DIR/test.parquet \
    data.train_batch_size=4096 \
    data.max_prompt_length=4096 \
    data.max_response_length=4096 \
    actor_rollout_ref.model.path=meta-llama/Llama-3.1-8B-Instruct \
    actor_rollout_ref.actor.optim.lr=1e-6 \
    actor_rollout_ref.model.use_remove_padding=True \
    actor_rollout_ref.actor.ppo_mini_batch_size=64 \
    actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=16 \
    actor_rollout_ref.model.enable_gradient_checkpointing=True \
    actor_rollout_ref.actor.fsdp_config.param_offload=True \
    actor_rollout_ref.actor.fsdp_config.optimizer_offload=True \
    actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=16 \
    actor_rollout_ref.rollout.tensor_model_parallel_size=16 \
    actor_rollout_ref.rollout.gpu_memory_utilization=0.8 \
    actor_rollout_ref.rollout.free_cache_engine=True \
    actor_rollout_ref.ref.log_prob_micro_batch_size=16 \
    actor_rollout_ref.ref.fsdp_config.param_offload=True \
    critic.optim.lr=1e-5 \
    critic.model.use_remove_padding=True \
    critic.model.path=meta-llama/Llama-3.1-8B-Instruct \
    critic.model.enable_gradient_checkpointing=True \
    critic.ppo_micro_batch_size=16 \
    critic.model.fsdp_config.param_offload=True \
    critic.model.fsdp_config.optimizer_offload=True \
    algorithm.kl_ctrl.kl_coef=0.001 \
    trainer.critic_warmup=0 \
    trainer.logger=console \
    trainer.val_before_train=True \
    trainer.n_gpus_per_node=8 \
    trainer.nnodes=2 \
    trainer.save_freq=-1 \
    trainer.test_freq=10 \
    trainer.total_epochs=15 2>&1 | tee verl_demo.log