
vLLM 在 RLHF 训练中的角色权重同步、Pause/Resume 与异步强化学习实战指南【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm在 RLHF基于人类反馈的强化学习等在线强化学习工作流中推理引擎需要与训练引擎高频协作策略模型每更新一轮推理侧的权重就必须同步刷新同时生成请求不能因此中断。vLLM 为此提供了可插拔的权重传输系统Weight Transfer、飞行中安全换权的 Pause/Resume API 以及一批官方 RLHF 示例脚本。读完本文你将掌握如何在 vLLM 中配置权重传输后端、如何在训练循环中驱动权重同步以及如何用异步流水线提升 GPU 利用率。vLLM 在 RLHF 工作流中的定位Reinforcement Learning from Human Feedback (RLHF) 是一种利用人类生成的偏好数据微调语言模型、使模型输出与期望行为对齐的技术。在 RLHF 及其他在线 RL 方法如 GRPO中策略模型在训练过程中被迭代更新而 rollout采样生成阶段必须由推理引擎高效完成并且更新后的权重必须实时反映到推理引擎中否则 rollout 使用的仍是旧策略训练将失去意义。vLLM 承担的就是其中的高速 rollout 角色。当前开源生态中多个主流 RL 库都使用 vLLM 来加速 rollout按字母序非穷举Cosmos-RL、ms-swift、NeMo-RL、Open Instruct、OpenRLHF、PipelineRL、Prime-RL、SkyRL、TRL、Unsloth、verl 等。vLLM 官方文档同时提供了 GRPO 的在线训练实践 notebook例如基于 TRL 的高效在线训练、基于 Unsloth vLLM 的 Qwen-3 4B GRPO可作为入门参考参见 docs/training/rlhf.md。要让 vLLM 真正融入 RL 训练循环需要解决两个核心问题权重如何从训练进程同步到推理引擎—— vLLM 的 Weight Transfer 系统 解决这一点提供 NCCL多卡分离部署与 IPC同卡共置部署等可插拔后端生成过程中如何安全地换权—— Async Reinforcement Learning 指南介绍的pause_generation/resume_generationAPI 解决这一点实现生成与训练的流水线化。权重传输系统架构与四阶段协议vLLM 的权重传输系统位于 vllm/distributed/weight_transfer/其核心设计是两个进程各持一个引擎、且两者对称训练进程Trainer process推理工作进程Inference workers类TrainerWeightTransferEngineWeightTransferEngine构建者WeightTransferTrainerFactory.trainer_init(...)vLLM 内部从WeightTransferConfig构建驱动方式send_weights()下方的四阶段协议持有物通信器、传输计划、wire 参数通信器、目标模型训练侧引擎是有状态的它持有自己的通信器与 wire 参数从WeightSource中拉取权重并通过VLLMWeightSyncClient驱动推理侧。训练代码无需了解底层传输协议每个同步轮次只需一次send_weights()调用。每一轮同步在底层都走同一套四阶段协议初始化init_weight_transfer_engine在训练循环开始前调用一次从trainer_init触发建立训练进程与推理工作进程之间的通信通道开始start_weight_update让推理引擎为一轮权重更新做好准备权重更新update_weights实际传输更新后的权重可调用一次或多次例如分块传输完成finish_weight_update收尾例如对 checkpoint 格式的权重做后处理所有权重传完后调用一次。可选的传输后端后端传输机制适用场景ncclNCCL broadcast训练与推理分布在不同 GPU上可跨节点ipcCUDA IPC handles训练与推理共置在同一 GPU上sparse_ncclNCCL broadcast基于 checkpoint 坐标的稀疏权重补丁sharded_rdtNIXL / Ray Direct Transport拉取式超大规模模型每个 worker 只需自己那片分片如专家并行的 MoE推理侧的配置只暴露一个后端选择器。WeightTransferConfig的定义见 vllm/config/weight_transfer.py其中backend字段为字符串选择器默认nccl在引擎创建时对照WeightTransferEngineFactory注册表做校验其余所有传输细节 rendezvous 参数、打包参数等都由训练侧决定并在初始化握手中下发推理侧不需要也不能与之“不一致”。快速上手两侧各写多少代码推理侧只声明后端from vllm import LLM from vllm.config import WeightTransferConfig llm LLM( modelmy-model, weight_transfer_configWeightTransferConfig(backendnccl), # 或 ipc、sparse_nccl、sharded_rdt )在线服务场景则直接用命令行vllm serve my-model \ --weight-transfer-config {backend: nccl}训练侧建一次引擎每轮调一次 send_weights()from vllm.distributed.weight_transfer import ( ModuleSource, HTTPVLLMWeightSyncClient, WeightTransferTrainerFactory, ) from vllm.distributed.weight_transfer.nccl_engine import NCCLTrainerInitInfo # 在训练循环开始前只构建一次。 engine WeightTransferTrainerFactory.trainer_init( init_infoNCCLTrainerInitInfo( master_addressmaster_address, master_portmaster_port, world_sizeworld_size, # 训练进程 全部推理 worker 的总数 rank0, # 本训练进程的 rankrank 0 是发送方 packedTrue, ), clientHTTPVLLMWeightSyncClient(http://localhost:8000), sourceModuleSource(model), ) # 每个权重同步轮次调用一次。 for step in range(num_steps): train_one_step(model) engine.send_weights()send_weights()会同时在推理侧驱动 start → update → finish并完成数据面传输包括后端所需的并发编排例如 NCCL 后端要求 worker 的update_weights与训练侧的 broadcast 同时执行因为两侧在同一个 NCCL 集合调用内汇合/rendezvous。训练侧没有backend参数每个TrainerInitInfo子类自带一个ClassVar形式的backend工厂按它分发。NCCL 后端分离部署与打包广播NCCL 引擎vllm/distributed/weight_transfer/nccl_engine.py适用于训练与推理分卡甚至跨节点的场景。详细文档见 docs/training/weight_transfer/nccl.md。工作原理训练进程与所有推理 worker 通过StatelessProcessGroupvLLM 提供的、不依赖 torch.distributed 全局组的抽象加入同一个 NCCL 进程组。训练侧是 rank 0worker 从rank_offset1开始编号训练侧向所有 worker 同时广播权重每个 worker 接收并加载可选的packed tensor 广播把多个小张量打包进大缓冲配合双/三重缓冲与 CUDA stream 重叠减少 NCCL 调用次数、提升吞吐。关键参数在NCCLTrainerInitInfo上字段默认值说明master_address—rendezvous 主机地址master_port—rendezvous 端口world_size—训练侧 全部 worker 的 NCCL 组大小rank—本训练进程的 rank关键字参数0 是发送方packedTrue是否使用打包广播packed_buffer_size_bytes1 GiB打包缓冲大小packed_num_buffers2轮换缓冲数量双/三重缓冲从源码结构看这里有一条重要的设计不变量wire 参数如packed故意不放在WeightTransferConfig或每轮的update_weights载荷里——训练侧在trainer_init时下发worker 只读取被告知值。这样两侧packed标志不一致的状态是“不可表达的”而不是“被不鼓励的”。NCCL 是少数同时读取WeightSource的metadata()与迭代字节流两条通道的后端引擎按metadata()构造每轮 update info 先发给 worker 用于确定接收缓冲尺寸与分块边界字节本身来自迭代source发送端会逐参数比对迭代结果与声明元数据一旦发散立即抛出异常指明首个不一致的参数而不是让坏数据上网络。ModuleSource天然满足该不变量自写WeightSource如 Megatron 导出、MoE 重融合时应把它作为首要测试项。内存方面轮换缓冲在整个传输期间都存活两侧各占用packed_buffer_size_bytes * packed_num_buffers默认配置下约 2 GiB显存紧张时调小packed_buffer_size_bytes。Sparse NCCL只传变化的元素sparse_nccl后端vllm/distributed/weight_transfer/sparse_nccl_engine.py用于按 checkpoint/Hugging Face 坐标表达稀疏、扁平索引的权重补丁每个推理 rank 收到相同的 checkpoint 全局补丁再由模型原生load_weights()映射到本 rank 的 TP/EP 与打包运行时参数。它是delta 型后端——每次调用携带的是替换补丁而非模型参数的稳定流因此不接受WeightSource补丁直接传给send_weights(patches)空补丁列表是 no-op单次调用即完整走一遍 start / update / finish。传输量为O(nnz)只发索引与值但 checkpoint 应用本身仍走原生 loader 的O(N)staging。支持张量并行且无需与训练侧布局一致。示例见 examples/rl/rlhf_sparse_nccl.pyQwen3 MoE 逐专家 checkpoint 更新1 个训练 GPU 2 个 TP2/EP2 推理 GPU。IPC 后端同卡共置、零拷贝IPC 引擎vllm/distributed/weight_transfer/ipc_engine.py通过CUDA IPC 句柄让训练与推理进程在同一 GPU上直接共享显存避免任何数据拷贝是共置部署下最高效的选择多 GPU 场景如 FSDP也支持每个 GPU 会先 all-gather 出完整权重再由正确的共置进程提取。详细文档见 docs/training/weight_transfer/ipc.md。流程概述训练侧为每个权重创建 CUDA 张量并用torch.multiprocessing.reductions.reduce_tensor生成 IPC 句柄多 rank 时FSDP每个 rank 先用ModuleSource在自己的 GPU 上物化完整张量所有训练 rank 的句柄经默认进程组 all-gather 合并按 GPU UUID 映射由发送方通过 client 下发每个 worker 只读取自己 GPU 对应的句柄推理 worker 用rebuild_cuda_tensor从句柄重建张量直接读训练侧显存。训练侧代码与 NCCL 几乎同构只是换成IPCTrainerInitInfofrom vllm.distributed.weight_transfer.ipc_engine import IPCTrainerInitInfo engine WeightTransferTrainerFactory.trainer_init( init_infoIPCTrainerInitInfo(rank0, packedFalse), # rank 0 是发送方 clientHTTPVLLMWeightSyncClient(http://localhost:8000), sourceModuleSource(model), ) engine.send_weights() # 每个同步轮次调用一次IPCTrainerInitInfo的字段字段默认值说明rank—本训练进程的 rank关键字参数0 是发送方packedFalse启用分块、内存有界的传输packed_buffer_size_bytes1 GiBpackedTrue时的分块大小两个实战要点分块传输默认所有权重在一次update_weights中发完要求两侧 GPU 同时装得下完整模型。packedTrue后权重被拼接进固定大小缓冲、按块分多次update_weights发送仍在一对 start / finish 括号内层式重载路径只初始化一次、收尾一次每块被消费后即可释放显存engine WeightTransferTrainerFactory.trainer_init( init_infoIPCTrainerInitInfo( rank0, packedTrue, packed_buffer_size_bytes256 * 1024 * 1024, # 256 MB 分块 ), clientclient, sourceModuleSource(model), )多 rank 训练时生产侧各块之间带跨 rank 屏障防止某 rank 覆盖缓冲时共置 worker 仍在读取当前块该逻辑内建在send_weights()中。HTTP 传输警告IPC 句柄是序列化 Python 对象走 HTTP 时必须在服务端与客户端都设置VLLM_ALLOW_INSECURE_SERIALIZATION1句柄会被 pickle 并 base64 编码传输。HTTP 服务端的权重同步端点以 HTTP server 方式运行 vLLM 时权重传输暴露以下端点HTTPVLLMWeightSyncClient会替你调用前四个端点方法说明/init_weight_transfer_enginePOST用后端特定信息初始化权重传输引擎/start_weight_updatePOST开始一轮权重更新/update_weightsPOST传输一批带后端特定元数据的权重/finish_weight_updatePOST完成更新可选择提交weight_version/update_weight_versionPOST不改变模型权重、只更新weight_version/weight_infoGET查询最新已提交的权重版本/pausePOST权重同步前暂停生成处理在途请求/resumePOST权重同步后恢复生成/get_world_sizeGET获取推理 worker 数量便于计算 NCCL world size注意HTTP 权重同步端点要求设置VLLM_SERVER_DEV_MODE1。此外Rust 前端的可选 gRPCControl服务为可信 sidecar 暴露同样的 pause、sleep、权重传输与权重版本生命周期ServerInfo.rl_capabilities响应会报告是否配置了权重传输与 sleep mode。无论走 HTTP 还是 gRPC后端特定的init_info/update_info都是 JSON 元数据张量本身始终走配置的 NCCL、IPC、sparse-NCCL 或 sharded-RDT 传输。多 rank 训练器FSDP / TP / PP / EP 下如何同步对于分片式训练器FSDP、TP/PP/EP每一个训练 rank 都要构建引擎并调用send_weights()Rank 0 是发送方只有它持有通信器、与 client 对话、真正把字节放上网络非发送 rank 也必须迭代WeightSource——因为物化一个参数本身通常就是集合通信如 FSDP 的full_tensor()all-gather、Megatron 导出若某些 rank 跳过就会死锁。每个进程在 init info 中传入自己的rank。它是显式参数而非从全局进程组读取因为同时存在 FSDP / TP / PP / EP 多个进程组时全局组语义是模糊的engine WeightTransferTrainerFactory.trainer_init( init_infoNCCLTrainerInitInfo(..., ranktorch.distributed.get_rank()), clientclient, sourceModuleSource(model), ) engine.send_weights() # 在所有 rank 上调用多 rank 场景的完整可运行示例examples/rl/rlhf_nccl_fsdp_ep.pyNCCL FSDP2 专家并行每个 FSDP rank 都构建引擎并参与full_tensor()gather仅 rank 0 触网与 examples/rl/rlhf_ipc_fsdp_ep.pyIPC FSDP2 共置于 4 张 GPU带 packed 分块与传输前后的 sleep/wake。异步 RLPause/Resume API 与典型循环在标准 RL 循环中生成与训练顺序执行策略生成 rollout → 训练 → 循环。生成期间训练卡闲置反之亦然。**一次性流水线one-off pipelining**方案把生成与训练拆成两个并行协程——一边用旧数据训练一边用当前策略生成新样本从而提升 GPU 利用率与训练吞吐。但重叠引入了一个难题必须在推理引擎仍在处理请求时、飞行中mid-flight更新权重。vLLM 的解法是pause_generation与resume_generation见 docs/training/async_rl.md。pause_generationawait engine.pause_generation(modekeep, clear_cacheTrue)mode决定在途请求如何处置Mode行为abort立即中止所有在途请求并返回部分结果默认wait等待所有在途请求完成后再暂停keep将请求冻结在队列中调用resume_generation时继续clear_cache决定暂停后是否清空 KV cache 与前缀缓存。resume_generationawait engine.resume_generation()暂停后恢复调度器。以modekeep冻结的请求将继续生成。HTTP 端点设置VLLM_SERVER_DEV_MODE1后vLLM HTTP server 通过以下方式暴露相同能力POST /pause?modekeep— 暂停生成POST /resume— 恢复生成POST /abort_requests— 中止在途请求但不暂停调度器发{}中止全部或{request_ids: [...]}指定GET /weight_info— 返回最新已提交的weight_version关于数据并行的一个重要区分使用 vLLM内建负载均衡器data_parallel_backendray时pause/resume 会自动在所有 DP rank 上生效调用一次即可使用外部负载均衡器多个独立 vLLM 实例置于代理之后时必须在权重更新前后向每一个引擎实例单独发送 pause 与 resume 请求。典型异步 RL 循环用当前策略开始生成 rollout训练器产生新权重后以modekeep暂停生成将训练器侧的新权重同步到推理引擎Weight Transfer 系统恢复生成——在途请求继续且带上新权重重复。这里的关键洞察是以modekeep暂停的请求在暂停前产出的 token 来自旧权重恢复后产出的 token 来自新权重。clear_cache决定 KV cache 是否被失效clear_cacheTrue时之前缓存的键值对全部丢弃恢复后生成的每个 token 都完全由新权重计算clear_cacheFalse时保留既有 KV cache 条目上下文中部分 token 仍反映旧权重陈旧 KV cache。是否可接受取决于算法对一致性的要求——GRPO 类方法通常按 rollout 批次边界对齐权重版本此时clear_cache的取舍直接影响同一请求内新旧 token 的混合程度。官方 RLHF 示例从哪份代码入手examples/rl/ 目录下有一组端到端可运行的 RLHF 示例覆盖各后端与部署形态是最直接的实战入口示例说明rlhf_http_nccl.py分离部署的起点。训练器占 1 张 GPU2× 张量并行 fp8 服务占另外 2 张HTTP 控制面 NCCL 数据面脚本自行拉起并销毁 serverrlhf_http_ipc.py共置部署的起点。server 与训练模型共享单张 GPUHTTP 控制面 CUDA IPC 数据面同样自管理 server 生命周期rlhf_async_new_apis.py异步权重同步的完整演示vllm.AsyncLLMEngine NCCL 传输 飞行中暂停/换权/恢复并开启 batch invariance 做确定性校验——把换权后的输出与一个直接加载训练模型的新 vLLM 实例逐 token 比对NVIDIA 要求 100% 精确匹配ROCm 放宽到 90%rlhf_nccl_fsdp_ep.pyNCCL FSDP2 专家并行的多 rank 训练器示例rlhf_ipc_fsdp_ep.pyIPC FSDP24 张 GPU 上与--data-parallel-size 4server 共置rlhf_sparse_nccl.pysparse NCCL 的逐专家 checkpoint 补丁Qwen3 MoE以 rlhf_async_new_apis.py 为例其核心编排清晰展示了异步 RL 的骨架训练模型Qwen3-1.7B与推理引擎Qwen3-1.7B-Base分别放在不同 GPU 的 Ray actor 中训练侧用RayVLLMWeightSyncClient直连引擎对象生成一批请求后任一请求达到 token 阈值即pause_generation(modekeep)调用broadcast_weights()内部即engine.send_weights()再resume_generation()脚本随后打印每个请求换权前后分别产出的 token 段并用新模型实例验证换权后的 token 与直接加载新权重的输出完全一致。延伸阅读与扩展点架构细节、四阶段协议与“每个配置项该放在哪一侧”的完整表格docs/training/weight_transfer/README.md基类WeightSource、VLLMWeightSyncClient、两个引擎 ABC 及其工厂注册表全部可替换docs/training/weight_transfer/base.md超大模型的拉取式分片传输docs/training/weight_transfer/sharded_rdt.mdNCCL / IPC 后端的参数与注意事项nccl.md、ipc.md入口 API 的导出列表vllm/distributed/weight_transfer/init.py整个系统的所有部件都可替换要发送的权重WeightSource、控制面传输VLLMWeightSyncClient内置 HTTP 与 Ray 两种 client也可自行适配、以及传输本身两个引擎 ABC 各自带工厂注册表。对于自建 RL 基础设施的团队这意味着可以把 vLLM 的权重同步层无缝嵌入自有的训练框架——只需实现自己的WeightSource或TrainerInitInfo子类即可复用四阶段协议、多 rank 语义与全部 HTTP/gRPC 端点。【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考