ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AI Infra知识点

AI Infra知识点 GPU 小常识GPU 基础知识入门一、GPU 是什么为什么需要它GPU 是为了大规模数据并行计算而生关键结论GPU 快不是因为单核通常单指令运行速度不如 CPU核多 访存带宽大 用并行掩盖延迟吞吐大处理多数据多计算比 CPU 总用时少。运行慢的大火车。二、GPU 硬件架构2.1 层次结构以 NVIDIA 为例GPU 芯片2.2 CUDA Core 数量怎么算CUDA Cores SM 数量 × 每 SM 的 FP32 单元数例如 RTX 309082 个 SM × 128 10496 个 CUDA Core。2.3 常见 GPU 规格对比三、内存层次性能优化的核心这是 GPU 编程里最重要的一张表几个关键认知访问全局显存比计算慢几百倍现代 GPU 算力增长远快于带宽增长因此绝大多数实际程序是”访存受限”memory-bound而非”计算受限”compute-bound。优化的第一原则往往是”减少访存 / 提高访存效率”而不是”减少计算量”。PCIe 是大瓶颈GPU 显存带宽: 2000 GB/s (A100 HBM2e)NVLink: 600 GB/sPCIe 4.0 x16: 32 GB/s ← CPU↔GPU 传输相差 60 倍以上。所以能不在 CPU 和 GPU 之间来回搬数据就不搬这是很多”GPU 用了却不快”的根本原因。Shared Memory 是手动管理的缓存矩阵乘法之类的算法靠把数据先搬到 Shared Memory 再复用tiling 分块能带来数倍加速。四、执行模型SIMT 与 Warp4.1 线程层级Grid一次 kernel 启动└── Block线程块最多 1024 线程 → 分配到一个 SM不迁移└── Warp32 个线程 → 硬件调度的最小单位└── Thread → 有自己的寄存器和程序计数器Block 内的线程可以通过 Shared Memory 通信可以 __syncthreads() 同步Block 之间默认无法同步这保证了 GPU 可以任意顺序调度 block可扩展性的来源4.2 SIMTSingle Instruction, Multiple Threads一个 warp 里 32 个线程共享一个指令流。这带来一个重要陷阱 —— 分支发散Warp Divergenceif (threadIdx.x % 2 0) {A(); // 偶数线程执行时奇数线程被屏蔽空转} else {B(); // 反之亦然}// 结果耗时 A B而不是 max(A, B)优化建议让分支尽量以 warp 为粒度对齐如 if (threadIdx.x / 32 0)而不是相邻线程走不同路径。4.3 延迟隐藏GPU 不靠大缓存降低延迟而是靠“人海战术”Warp0 发起访存 → 等待 400 周期↓ 调度器立刻切到Warp1 计算 → Warp2 计算 → Warp3 …↓ 400 周期后Warp0 数据到了继续Warp 切换是零开销的寄存器都是各自独立预分配的。所以 SM 上驻留的 warp 越多越能填满流水线 —— 这就是 Occupancy占用率 的意义。五、CUDA 编程模型入门5.1 最小完整例子向量加法#include//global表示这是在 GPU 上执行、由 CPU 调用的核函数globalvoid vecAdd(const float* a, const float* b, float* c, int n) {int i blockIdx.x * blockDim.x threadIdx.x; // 全局唯一线程 IDif (i n) { // 边界检查必不可少c[i] a[i] b[i];}}int main() {int n 1 20; // 1M 元素size_t bytes n * sizeof(float);// 1. 主机端分配与初始化floath_a (float)malloc(bytes);floath_b (float)malloc(bytes);floath_c (float)malloc(bytes);for (int i 0; i n; i) { h_a[i] 1.0f; h_b[i] 2.0f; }// 2. 设备端分配float *d_a, *d_b, *d_c;cudaMalloc(d_a, bytes);cudaMalloc(d_b, bytes);cudaMalloc(d_c, bytes);// 3. 拷贝 Host → DevicecudaMemcpy(d_a, h_a, bytes, cudaMemcpyHostToDevice);cudaMemcpy(d_b, h_b, bytes, cudaMemcpyHostToDevice);// 4. 启动 kernelblock数, 每block线程数int threads 256;int blocks (n threads - 1) / threads; // 向上取整vecAddblocks, threads(d_a, d_b, d_c, n);// 5. 拷回 Device → HostcudaMemcpy 隐含同步cudaMemcpy(h_c, d_c, bytes, cudaMemcpyDeviceToHost);printf(“c[0] %f\n”, h_c[0]); // 3.0// 6. 释放cudaFree(d_a); cudaFree(d_b); cudaFree(d_c);free(h_a); free(h_b); free(h_c);return 0;}编译运行nvcc -archsm_86 -O3 vecadd.cu -o vecadd./vecadd5.2 三个函数修饰符5.3 异步与 StreamKernel 启动是异步的CPU 发完就返回这是新手常见的坑kernelb, t(…);cudaDeviceSynchronize(); // 计时或读结果前必须同步// 错误检查异步错误只能同步后拿到cudaError_t err cudaGetLastError();if (err ! cudaSuccess) printf(“%s\n”, cudaGetErrorString(err));用 Stream 可以让拷贝和计算重叠cudaStream_t s1, s2;cudaStreamCreate(s1); cudaStreamCreate(s2);cudaMemcpyAsync(d_a, h_a, bytes, cudaMemcpyHostToDevice, s1);kernelb, t, 0, s1(d_a, …); // s1 内串行s1 与 s2 并行六、性能优化的核心概念6.1 Roofline 模型先判断瓶颈在哪计算强度 (Arithmetic Intensity) 浮点运算次数 / 访存字节数 (FLOP/Byte)强度低如向量加法3 次访存换 1 次加法约 0.08→ 访存受限优化访存强度高如大矩阵乘法→ 计算受限优化指令与 Tensor Core 利用A100 的临界点约为 19.5 TFLOPS / 2 TB/s ≈ 10 FLOP/Byte。多数深度学习算子激活、归一化、element-wise都远低于这个值属于访存受限这也是算子融合kernel fusion如此有效的原因。6.2 合并访存Coalescing一个 warp 的 32 个线程如果访问连续对齐的地址硬件可以合并成少数几次内存事务// 好线程 i 访问 data[i]连续float v data[blockIdx.x * blockDim.x threadIdx.x];// 坏跨步访问一次 warp 触发 32 次事务带宽利用率降到 1/32float v data[threadIdx.x * 32];这通常是性能差异最大的单个因素。相应地数据布局上 SoA结构体数组优于 AoS数组结构体。6.3 Shared Memory 与 Bank ConflictShared Memory 分为 32 个 bank。同一 warp 内多个线程访问同一 bank 的不同地址会串行化。经典解法是 paddingsharedfloat tile[32][33]; // 33 而非 32错开 bank6.4 Occupancy占用率Occupancy 实际驻留 warp 数 / SM 支持的最大 warp 数限制因素每线程寄存器数、每 block 的 Shared Memory 用量、block 大小。注意占用率不是越高越好60%~70% 通常就足够隐藏延迟有时降低占用率换取更多寄存器提高 ILP反而更快。6.5 优化优先级清单如下减少 CPU↔GPU 数据传输保证全局内存合并访问用 Shared Memory 复用数据tiling算子融合减少 kernel 启动和中间结果读写避免 warp 分支发散调整 block size通常 128/256为 32 的倍数用 Tensor Core / 低精度用 Stream 重叠计算与传输七、Tensor Core 与精度Tensor Core 是专门做 D A × B C 小矩阵乘加的单元比 CUDA Core 做同样的事快一个数量级。常见数值格式PyTorch 中启用混合精度from torch.amp import autocast, GradScalerscaler GradScaler()for x, y in loader:with autocast(‘cuda’, dtypetorch.bfloat16):loss model(x, y)scaler.scale(loss).backward()scaler.step(optimizer)scaler.update()另外可打开 TF32对 Ampere 有效torch.backends.cuda.matmul.allow_tf32 Truetorch.backends.cudnn.allow_tf32 True八、多 GPU 与互联常见并行策略数据并行DDP每卡一份完整模型切分数据梯度 AllReduce张量并行TP把单层的矩阵切开放到多卡通信频繁需 NVLink流水线并行PP不同层放不同卡ZeRO / FSDP切分优化器状态、梯度、参数省显存九、软件生态应用层 PyTorch / TensorFlow / JAX / vLLM↓库层 cuBLAS(矩阵) cuDNN(卷积) cuFFT NCCL(多卡通信)CUTLASS(模板库) Thrust(类STL) TensorRT(推理)↓编程层 CUDA C / Triton / OpenAI Triton / CUDA Python↓驱动层 CUDA Runtime → CUDA Driver → GPU版本关系要点显卡驱动版本 决定支持的最高 CUDA 版本nvidia-smi 右上角显示的是驱动支持的最高版本CUDA Toolkit 版本nvcc -V 显示是你编译用的版本可以低于驱动支持的PyTorch 的 pip 包自带 CUDA runtime本机不装 CUDA Toolkit 也能跑只要驱动够新常用工具nvidia-smi # 查看显存占用、利用率、驱动版本nvidia-smi dmon -s u # 实时监控 SM/显存/编解码利用率nsys profile ./app # Nsight Systems整体时间线找 CPU/GPU 空隙ncu --set full ./app # Nsight Compute单 kernel 级别深度分析compute-sanitizer ./app # 检测越界、竞态替代旧的 cuda-memcheckPyTorch 内置分析器from torch.profiler import profile, ProfilerActivitywith profile(activities[ProfilerActivity.CPU, ProfilerActivity.CUDA]) as prof:model(x)print(prof.key_averages().table(sort_by“cuda_time_total”, row_limit15))十、常见误区十一、术语速查简单来说RL 的训练不是“模型训一次”而是“模型先生成一堆样本Rollout再拿这些样本训一次Update”的循环。PPO 是这样GRPO 更是把这个循环放大了一次要生成一组 G 条回答所以对基础设施Infra的设计压力主要就集中在怎么平衡“生成”推理/rollout和“训练”更新的算力、显存和时间。本文以 GRPO 为例讲清楚当前主流 RL 框架在 Infra 层基础架构是怎么设计的。一、GRPO 决定了 RL Infra 的需求先看 GRPO 和 PPO 的差异这个差异直接决定了框架怎么分配 GPU。DeepSeek-R1 的实践也印证了这一点GRPO 的瓶颈大部分时候是 Rollout采样生成而不是 Policy Update参数更新。所以 GRPO 的 Infra 设计核心是如何高效地完成“大规模采样Rollout”这个阶段。二、RL 训练的核心组件一个 RL 训练流程可以拆成下面几个关键组件GRPO 的一个训练步Step大致是问题在于Step 2Rollout是自回归生成串行 token-by-tokenStep 6Update是大矩阵并行训练批处理。这两个阶段的计算特征完全不同推理 vs 训练硬件利用方式也不同。三、Colocated vs Decoupled耦合 vs 解耦当前主流 RL 框架最核心的 Infra 架构决策就是Rollout 和 Training 用同一批 GPU还是用不同批 GPU3.1 解耦Decoupled / Training-Inference Separated思路把“推理Rollout”和“训练Update”完全分开在两组 GPU甚至两组机器上跑。Rollout 集群只跑推理引擎vLLM、SGLang、TensorRT-LLM追求吞吐tokens/s和延迟通常开 Tensor ParallelTP、Continuous Batching、PagedAttention 等推理优化。Training 集群只跑训练FSDP/Megatron追求显存利用率和计算效率ZeRO/FSDP、TP/PP、梯度累积等。优点资源利用专业化推理和训练的配置batch size、并行方式、内存分配策略互相冲突。分开后各自调优空间大GPU 利用率更稳定。扩展性好Rollout 特别吃生成吞吐可以单独横向扩展 Rollout 节点应对 G 很大的场景比如 G64。不内存争抢vLLM/SGLang 跑时要占 KV Cache 模型权重训练要占模型权重 优化器状态 梯度 激活值。分开就不会互相挤显存。缺点需要参数同步/搬运每一轮 RL StepActor 更新完参数之后必须把新权重同步到 Rollout 引擎。对于 7B/32B/70B 参数量这个同步是一次显著的开销尤其是跨节点走网络。GPU 空泡BubbleTraining 跑完 Update 要等 Rollout 跑完一轮Rollout 跑完要等 Training 同步完参数再下一轮。两边耗时不一定匹配很容易有一边空闲。代表框架早期的 OpenRLHF支持 decoupled部分生产场景也用这个思路。3.2 耦合Colocated / Training Inference Shared GPUs思路让同一批 GPU 既跑 Rollout推理也跑 Training训练。核心是同一轮里先用这些 GPU 做生成生成完再立刻切换成训练模式做参数更新。优点零参数跨机搬运Weight SharingActor 的权重就在 GPU 显存里Rollout 用完直接切到 Training不需要 broadcast/push weights 到另一组集群省去了大量网络传输和同步等待时间。显存利用更充分理想情况下可以减少“整组 GPU 只做生成时的空闲算力”。尤其是生成结束到更新开始之间的空档更小。硬件成本更低同样规模的模型不用拆成两套集群用一套 GPU 就能跑。缺点显存极度紧张一块 GPU 上要同时扛住两种峰值内存推理峰值模型权重 KV Cache长上下文大 batchG 条回答时 KV Cache 非常吓人训练峰值模型权重 优化器状态Adam 2~3x 梯度 激活值Activation资源争抢与切换开销vLLM/SGLang 是独立的推理引擎C/CUDA 执行图FSDP/Megatron 是训练框架。要在同一批 GPU 上“轮流运行”通常需要重载权重weight reloading或者引擎内部分时复用实现起来复杂容易有内存碎片。调优困难推理和训练的并行策略TP/DP/PP往往是冲突的。比如训练想要大 DP 提升吞吐推理想要 TP 降低单卡显存压力很难两全。代表框架veRL主推 HybridFlow ColocatedSkyRL 也偏向 colocated 思路Slime 则探索了“异步Async”的方式来缓解空泡。3.3 主流选择目前业界共识是7B~14B 小模型更适合 Colocated省同步开销显存压力勉强能顶32B~70B 大模型更倾向 Decoupled显存太吃紧宁可忍受参数同步开销。这也是为什么 veRL字节/火山在主流规模7B/14B RLVR里大幅采用 Colocated而一些大规模训练70B还是会选 Decoupled 架构。四、veRL 的 Infra 设计最具代表性veRL 是目前 GRPO 研究和落地里最常用的框架之一。它的核心设计思想叫 HybridFlow混合流程本质上是用 Ray 做分布式编排 Worker 抽象封装不同角色 支持 Colocated/Decoupled 灵活切换。4.1 整体架构Ray WorkerveRL 用 Ray 作为全局控制器Orchestrator。Ray 的好处是可以把不同的任务Rollout、Reward、Update调度到不同 GPU/节点上处理异步、容错和资源分配都比较方便。核心是把系统拆成一堆 Worker工作单元每个 Worker 绑定一组 GPU负责某个角色4.2 Colocated 模式下的时序GRPO Step以 ActorRolloutRefWorker Colocated 为例一步 GRPO 的时序大致如下123456789101112131415161718T0: Prompts (Ray Data/Buffer)↓GPU 组: Rollout 阶段推理模式加载/切换到推理态vLLM/SGLang 接管执行每个 Prompt 采样 G 条 Completion自回归吞吐主导同时保存 log_probs_oldπ_{θ_old} 在生成时的对数概率避免后面重算生成路径的 logprob输出 Trajectoriestokens, logprobs_old, response_ids…↓GPU 组: 计算 Reward AdvantageRewardWorker可异步算分组内归一化得到 A_i拼成训练 BatchExperience↓GPU 组: Training/Ref 阶段训练模式切回 FSDP/Megatron 训练态权重仍在显存无需跨卡搬运计算 Ref log-probs冻结 Ref前向即可显存/算力开销小用 GRPO Loss 计算 π_θ/π_{θ_old} 的 Importance Sampling Ratio做 Clip反向更新 Actor↓下一轮 Step用更新后的 θ_{new} 直接做 Rollout权重已在显存关键点log_probs_old 在 Rollout 阶段一边生成一边顺带算出来vLLM/SGLang 支持返回采样路径的 log-prob而不是生成完再让 Actor 重算一遍整段序列的 log-prob。这样既省计算又保证是 πold 在真正采样时的概率数值更一致。4.3 Decoupled 模式下的时序1234567Rollout GPUsvLLM/SGLang推理- 生成 G 条回答产出 trajectories log_probs_old- 通过 Ray/Object Store 或网络把 Experience Batch 推送到 Training GroupTraining GPUsFSDP/Megatron训练- 收到 Batch计算 Advantage、Ref Log-probs、GRPO Loss更新 Actor 权重 W_{t1}- 将 W_{t1} 同步Weight Sync回 Rollout GPUsBroadcast/CheckpointLoad 或直接 NCCL/Ray- 下一轮用新权重 W_{t1} 做 Rollout这里的权重同步Weight Synchronization是 Decoupled 架构的最大开销点。veRL、OpenRLHF 等框架会尽量用 NCCLGPU 间高速互联做同步而不是走 CPU 存中转来减少延迟。五、关键 Infra 设计点GRPO 场景GRPO 对 Infra 提出了几个特别的工程挑战主流框架基本都围绕这些点优化。5.1 Rollout 引擎的选择Rollout 是生成密集型必须用高吞吐的推理引擎而不是直接用 PyTorch eager 做自回归。GRPO 的一个细节需要 Rollout 阶段返回每个 token 的 log_prob给 Importance Sampling 用。vLLM/SGLang 都原生支持 logprobs/token_logprobs这也是它们能成为 RL Rollout 引擎事实标准的原因。5.2 Colocate 的显存管理Colocated 最大痛点是显存竞争。主流做法是“推理时优先保证 KV Cache 权重训练时优先保证激活优化器”框架层会做显存预估和时序切换。一些优化思路Offload/Swap训练时暂时把 vLLM 的 KV Cache offload 到 CPU/显存空闲区域或者直接释放引擎占用的缓存等下一轮 Rollout 再重新预分配。代价是 CPU-GPU 拷贝开销。Paged KV 管理vLLM 的 PagedAttention 本身就大幅降低 KV 峰值减轻了与训练的内存冲突。序列长度动态变化GRPO 生成的回答长度差异很大长短 CoT容易导致显存波动Continuous Batching 动态分配就很关键。权重共享不复制Colocated 的核心优势就是“权重常驻显存”。理想做法是 Actor 权重训练格式 FSDP/Megatron和 Rollout 权重推理格式 FP16/FP8TP 切分方式不同复用同一份显存权重避免内存 double。veRL 在 FSDP vLLM同 DP/Shard 或权重统一这条路径上有这方面的优化。5.3 数据流与 Experience BufferRollout 一次产出是 (Prompts × G) 条 trajectoriestoken 数量可达数千万 token/step。如何高效传递给 Trainer 是个工程问题。主流做法内存共享Zero-Copy用 Ray 的 Object Store分布式共享内存或者 GPU Direct避免把大批 token 数据从 GPU 拷到 CPU 再拷回 GPU。就地In-Place传递在 Colocated 模式下Trajectories 还在同一组 GPU 的显存上Trainer 直接读取对应张量减少拷贝。打平Flatten Padding/Mask不同回答长度不一需要做 padding attention mask loss maskGRPO 通常是只算 completion 部分的 loss。5.4 并行策略的兼容TP/DP/FSDP/Megatron训练和推理的并行方式天然不同Colocated 的难点同一批 GPU 同时要跑 FSDPSharded Data Parallel和 vLLMTensor Parallel。这两种并行的切分方式不一致权重在显存的布局Layout不同。如果强行共用需要做权重重排Weight Resharding。veRL 在某些组合FSDP vLLM TP下会做权重转换/同步Decoupled 则直接各自用最合适的并行方式靠 Weight Sync 解决布局差异。六、主流 RL Infra 框架对比GRPO 场景下面按架构思路对主流框架做个对比便于理解当前设计趋势。七、Colocated vs Decoupled 的核心权衡总结简单概括成一张表八、Infra 设计趋势目前 GRPO/RLVR 的 Infra 正在朝两个方向演进向 Colocated 优化想尽办法解决显存竞争PagedAttention、引擎显存预留、动态 offload、权重格式统一。veRL/SkyRL 都在往这个方向打磨目标是“能跑起来 32B Colocated”。向 Async异步演进Slime 提出的思路是打破严格 On-Policy 的 Step 同步约束让 Rollout 和 Update 流水线化Pipeline旧策略 Rollout 和新策略 Update 可以错开执行以此掩盖空泡Bubble。这类做法是牺牲一点 On-Policy 严格性换取更高的 GPU 吞吐利用率在长 CoT 场景特别有效。简单总结GRPO 的 Infra 核心矛盾是“生成串行、自回归 vs 训练并行、批处理”这两种完全不同的负载如何高效共处。Colocated 想省去“参数搬运”这个代价代价是“显存打架”。Decoupled 想省去“显存打架”这个代价代价是“参数搬运 同步空泡”。主流框架尤其是 veRL选择的是“HybridFlow”给你两种都能选让你根据模型规模7B/32B/70B、回答长度短回答 vs 长 CoT、采样组数 G 去权衡这个 trade-off。这才是当前 RL Infra 设计最贴合实际落地的思路。slimeSGLang-native 的 RL Scaling 框架slime 是 THUDM清华 / 智谱开源的 LLM 后训练框架专为 RL Scaling 设计是 GLM 系列模型GLM-4.5 / 4.6 / 4.7 及后续版本实际 RL 后训练所用的框架。它的定位很明确Megatron 做训练 SGLang 做 rollout中间用一个可编程的 Data Buffer 连接三者由 Ray 统一编排。两大核心能力高性能训练通过连接 Megatron 与 SGLang支持多种模式下的高效训练灵活的数据生成通过自定义数据生成接口和「服务化」的推理引擎可以实现任意复杂的训练数据生成流程多轮对话、工具调用、代码沙箱、搜索、多智能体……。一、slime 的设计出发点RL 后训练 Infra 的核心矛盾是 生成自回归、串行、长尾vs 训练批处理、并行生成端一个 token 一个 token 往外吐单条序列长度不可预知GPU 并行度再高也得等「这一条写完」训练端一切讲究整齐——定长 batch、大规模矩阵乘、多维并行切分最怕数据不齐、GPU 空等。slime 观察到的几个具体痛点slime 的回答是把 rollout 彻底解耦成「一个可以任意编程的异步服务调用」训练端保持 Megatron 的全部并行能力中间用 Buffer 解耦时序。这句话拆开看有三个决定每一个都对应一个痛点Rollout 服务化SGLang as a service→ 解决「agentic rollout 难写」生成变成普通 HTTP 调用用户爱怎么编排怎么编排训练端坚持 Megatron → 解决「MoE 大规模并行」TP/PP/EP/CP 全套保留Buffer 做中间人 → 解决「长尾 时序耦合」生成和训练节奏解耦还能顺带做样本过滤、partial rollout 缓存。二、三模块架构slime 把系统拆成三个角色用 Ray 编排Ray 负责跨节点的进程调度、资源分配与 actor 间通信数据流一次 RL 迭代的视角Data Buffer 从数据集取出 prompt交给用户自定义的 rollout 函数rollout 函数通过 Router 向 SGLang Server 发起生成请求可能多轮、带工具调用拿到回答 token 级 logprobreward/verifier 打分后样本写回 Data BufferBuffer 攒够一个训练 batch过滤、打包、padding、loss mask交给 MegatronMegatron 完成一次梯度更新后把新权重同步回所有 SGLang Server进入下一轮。2.1 TrainingMegatron-LM承担 Actor 更新 Reference 模型 log-prob 计算GRPO 里用于 KL 正则保留 Megatron 完整的并行能力TP / PP / EP / CP / VPP这是 slime 相对很多 FSDP-only 框架的硬优势MoE 大模型如 GLM-4.5 的 MoE 结构、DeepSeek-V3 结构能真正跑起来。FSDP 以数据并行为主对 MoE 的专家并行EP支持很弱而 EP 恰恰是 MoE 模型训练的刚需——每个专家只放在部分卡上All-to-All 通信调度由 Megatron 成熟实现后续也加入了 FSDP 后端作为轻量选项方便中小模型快速上手slime 的一个设计理念是「参数直通」Megatron 的参数直接透传SGLang 的参数以 --sglang- 前缀暴露上游引擎的新优化可以直接用框架本身不做一层「最大公约数」式的封装。为什么不用「训推一体」的框架 训练和推理对引擎的要求完全不同训练要反向传播、优化器状态、梯度通信推理要 KV cache 管理、连续批处理continuous batching、前缀缓存。强行在一个引擎里同时做好两件事往往两头不讨好。slime 的选择是让两个各自最强的引擎各干各的代价是引入「权重同步」这个工程难题见 4.2。2.2 RolloutSGLang Router关键设计SGLang 以「服务」形式存在而不是以「库」形式被调用。起若干个 SGLang Server每个 server 内部可以 TP/DP/EP推理侧也能吃满 MoE 并行前面挂一个 Router 做负载均衡把请求分发到各 server训练侧通过 OpenAI 兼容的 HTTP 接口 请求生成——chat/completions 那套任何语言、任何 agent 框架都会调。这一步看似简单影响却很大——它把 rollout 从「框架内嵌的一段 generate 代码」变成了「任何 Python 代码都能调用的服务」你想做多轮工具调用写个 while 循环调 API 就行你想接外部搜索、代码沙箱在两次调用之间插入任意逻辑你想用现成 agent 框架LangGraph 之类它本来就会调 OpenAI 接口。对比「库形式」的方案框架内部直接调推理引擎的 Python API引擎升级要动框架自定义逻辑要改框架源码agentic 流程更是寸步难行。2.3 Data Buffer最有特色的部分Buffer 不只是个队列它是用户可编程的 rollout 编排层。用户通过实现一个 generate_rollout 函数来完全控制数据怎么生成伪代码用户自定义的 rollout 函数async def generate_rollout(args, rollout_id, data_buffer, evaluationFalse):prompts data_buffer.get_samples(args.rollout_batch_size)tasks []for p in prompts:for _ in range(args.n_samples_per_prompt): # GRPO 的 G每个 prompt 采 G 条tasks.append(rollout_one§)samples await asyncio.gather(*tasks) # 全部并发跑return post_filter(samples) # 过滤见 4.3async def rollout_one(prompt):msgs [{“role”: “user”, “content”: prompt}]for turn in range(MAX_TURNS): # 多轮 / agenticresp await sglang_client.chat(msgs,return_logprobTrue) # GRPO 需要 old logprob 算 ratioif has_tool_call(resp):obs await run_tool(resp) # 工具 / 代码沙箱 / 搜索msgs [resp, obs]continuebreakreward await verifier(prompt, resp) # rule / model / sandbox 打分return Sample(tokens…, logprobs…, rewardreward,loss_maskmask_out_tool_output()) # 关键屏蔽环境返回见 4.4注意 return_logprobTrue 这一行GRPO/PPO 类算法需要计算 importance ratio πθ/πold其中分母是生成时策略的 logprob必须在 rollout 阶段就记录下来不能事后重算推理引擎和训练引擎的数值实现有差异事后重算会引入偏差。Buffer 同时负责三、两种运行模式slime 同时支持同步 colocated 和异步 disaggregated这是它的核心灵活性。先理解这两个维度是独立的Colocated vs Disaggregated训练和生成是否共用 GPU空间维度同步 vs 异步生成和训练是否等待彼此时间维度。3.1 Colocated Synchronous同 GPU、同步一组 GPU 分时复用生成时把 Megatron 的优化器状态/梯度 offload 到 CPU训练时释放 SGLang 的 KV Cache严格 on-policy生成用的权重和训练用的权重严格一致算法行为最干净适合中小规模、算法研究、需要严格复现的场景。3.2 Disaggregated Asynchronous分离、异步这是 slime 最主打的模式关键Rollout 不等训练训练不等 Rollout。Rollout 集群持续满负荷生成永远有活干训练集群一攒够一个 batch 的数据就更新权重更新后异步推给 RolloutRollout 在下一条请求开始用新权重已在飞行中的请求继续用旧权重跑完保证单条样本内部一致性。代价是引入 off-policy 偏差训练时用的样本可能是 1~2 个版本之前的权重生成的。slime 的处理方式Staleness 上限约束比如最多落后 1 个 step把偏差控制在可接受范围对应参数如 --async-buffer-size、–update-weights-interval控制缓冲多少批数据、隔几次采样同步一次权重算法自带容忍度GRPO/PPO 本身就有 importance sampling ratioclip 机制clip 会把 ratio 偏离 1 太远的样本梯度截掉对轻度 off-policy 有一定容忍度实践验证1-step 异步对最终效果影响很小但吞吐提升显著。直观理解 staleness想象你在教一个不断进化的学生做题。同步模式 学生每学会一点就立刻用新水平出新题给自己做异步模式 老师训练端和学生生成端各干各的学生做的题可能基于「稍微过时」的水平。只要别落后太多staleness ≤ 1教学效果几乎不变但两边都不用等对方总吞吐接近翻倍。四、slime 的几个关键技术点4.1 Partial Rollout长尾杀手这是针对 long CoT 最有效的优化之一。问题一个 batch 里 95% 的回答 2K token 就结束剩下 5% 要跑到 32K。同步等待意味着 95% 的算力在最后阶段闲置——GPU 数量没变但干活的人从几百个变成几个。做法给 rollout 设一个「预算」时间或 token 数。到点还没生成完的序列不硬等而是截断、缓存、下一轮接着生成效果消除长尾等待每个 step 的生成都按时长/token 预算「齐步走」GPU 利用率大幅提升副作用一条序列可能横跨多个权重版本「缝合」样本——前半段是权重 k 生成的后半段是权重 k1 生成的是一种更强的 off-policy需要配合 staleness 控制和 importance ratio 处理本质上这是把「按样本同步」改成了「按预算同步」用一点点算法上的近似换巨大的吞吐收益。4.2 参数同步Megatron → SGLang这是 disaggregated 架构的关键开销点。两边权重布局完全不一样不能直接拷slime 的处理两种模式走不同的 API 路径工程上还有一串针对 MoE 的优化MoE 模型有大量小张量——每个专家的权重都不大但数量多异步聚合训练端合并 DP/TP/EP 分片时流水线化聚合和传输重叠吃满带宽桶更新SGLang 侧通过请求更新权重按桶批量更新避免「一个 tensor 一次请求」的开销合并小张量减少 CUDA IPC 句柄的频繁创建和清理缓存元信息重复的切分查询只算一次。对 100B MoE 模型这块工程量很大也是 slime 相对成熟的地方——权重同步如果做得粗糙每步可能要花几分钟直接抵消异步架构的收益。4.3 GRPO 专属零方差组过滤/动态采样GRPO 的 advantage 计算组内归一化如果一组 G 条全对reward 全 1或全错全 0→ std0advantage 全为 0梯度为零。直觉上模型从「大家都一样」的组里学不到任何东西——没有比较就没有方向。在数学/代码 RLVR 里简单题全对、难题全错的比例可能高达 40%意味着近一半的生成算力被浪费。slime 在 Buffer 层做 over-sampling dynamic filteringDAPO 的思路valid []while len(valid) target_batch_size:batch await rollout(oversample_ratio * target) # 多采一些for group in group_by_prompt(batch):if std(group.rewards) eps: # 组内有区分度才保留valid.extend(group)为什么这个策略在异步架构下特别自然同步框架里过滤掉的样本意味着训练侧干等重采——GPU 空转而在 slime 的异步架构里Rollout 集群本来就在持续产出、Buffer 里永远有存货过滤只是「从更大的池子里挑好的」训练侧完全无感。这是「架构红利」的一个典型例子同样的算法技巧换个架构就从「昂贵」变成「免费」。4.4 Loss Mask 与多轮/工具场景agentic rollout 里序列 用户输入 模型输出 工具返回 模型输出 …。工具返回的 token 不是模型生成的绝不能算 loss——否则模型会学着「模仿工具返回格式」而不是学会「决定什么时候调工具」。slime 让用户在自定义 rollout 函数里直接构造 loss_mask1 算 loss0 跳过把环境 token 屏蔽掉这在把 rollout 写死在框架里的方案中往往需要改框架源码而在 slime 里只是用户函数里多写几行。五、slime 的优势总结RadixAttention 对 GRPO 的意义值得单独说在 GRPO 里 G 通常 8~32prompt 又常常很长few-shot 示例、系统提示、题目描述。如果没有前缀复用G 条回答要重复 prefill G 次同样的 prompt——G16 意味着 15⁄16 的 prompt prefill 是纯浪费。RadixAttention 把 KV cache 组织成基数树相同前缀自动命中缓存• 省 prefill 计算prompt 只算一次G 条样本共享• 省 KV 显存前缀的 KV 只存一份G 越大、prompt 越长优势越明显——这恰好就是 RLVR 的典型负载形态。可以说 GRPO 和 RadixAttention 是「天作之合」这也是 slime 选择深度绑定单一推理引擎而不是抽象适配多个引擎、落到最大公约数能力的核心回报之一。六、与 verl/OpenRLHF 的定位对比三者背后的设计哲学差异slime押注「单一最优组合」Megatron SGLang用深度绑定换极致性能和简洁抽象面verl押注「最大灵活性」用混合执行引擎hybrid engine和广泛适配换生态广度OpenRLHF押注「经典 RLHF 流程的易用性」DeepSpeed 栈对很多团队更熟悉。02选型建议选 slime要做 agentic RL多轮工具调用、代码执行、搜索、环境交互训 大规模 MoE 模型long CoT 长尾严重需要异步 / partial rollout 榨 GPU 利用率已有 Megatron SGLang 技术栈。选 verl想尝试多种 RL 算法变体、跟进最新论文实现需要最大的社区支持和文档中等规模 dense 模型7B~32B的标准 RLVR。选 OpenRLHF经典 RLHF 流程SFT → RM → PPO团队熟悉 DeepSpeed。七、需要注意的代价slime 的优势不是免费的异步 off-policy。partial rollout 更是让单条序列跨版本。虽然有 clip staleness 控制但在某些任务上仍可能影响收敛稳定性需要调 staleness 上限、监控 importance ratio 分布如果大量样本 ratio 被 clip说明 off-policy 程度已经影响学习了。Megatron 门槛。并行配置TP×PP×EP×CP 怎么组合才不把显存/通信打爆、checkpoint 转换、debug 难度都高于 FSDP。FSDP 是「一键切分」Megatron 是「手动调琴」。调试复杂度。Ray 多进程 HTTP server 异步出问题时定位链路长是 rollout 慢权重没同步还是 buffer 卡住。slime 提供了 rollout-only / train-only 的独立调试路径和 trace 工具但最稳妥的建议仍然是先用同步 colocate 模式跑通再切异步。算法生态相对精简。想直接用某个冷门算法变体可能得自己实现——好在 GRPO 家族的变体大多只需要改 advantage 计算和 Buffer 过滤逻辑改起来不算深。八、一张图回顾全文
返回列表