
最近几个月但凡聊 LLM 的后训练话题绕不开 GRPO。从 DeepSeekMath 把这个方法推到台前到 SimpleRL 证明“纯强化学习也能出效果”再到 DAPO 把几个关键技巧系统化整理出来GRPO 已经从论文里的小改动变成了 LLM 强化学习LLM RL最常用的训练范式之一。这篇博文想做的事情很简单把这一段时间陆续做的 GRPO 训练评测做一个汇总覆盖三篇论文、累计折算 40 万 GPU 时的实验体量把十余项训练技巧的动机、效果、参数和坑都讲一遍。适合正在做 LLM post-training、准备从 PPO 切到 GRPO、或者已经在跑 GRPO 但觉得“训练不稳定、奖励不涨、熵掉太快”的工程师看。先说结论GRPO 没有想象中那么玄学但也不是照着开源仓库拉起来就能稳定出效果。真正决定成败的往往不是损失函数本身而是采样质量、动态过滤、长文本处理和工程缓存这些“训练技巧”。下面按技术拆解、算力账、可抄配置、问题排查四个大块来说。1. 为什么 GRPO 成了 LLM RL 的默认打开方式1.1 PPO 在 LLM 尺度上太贵了PPO 做 LLM 对齐训练侧要维护一个和 Actor 同等量级的 Critic 价值网络。对 7B 模型还好对 70B 模型就非常难受价值网络的前向反向要占掉一大块显存和算力而且价值网络本身还会引入额外的方差来源。传统 PPO 在游戏、机器人领域是因为单步 state 的价值可学、有明确 reward 信号Critic 才能学得准但 LLM 场景里 state 是一整段上下文价值函数经常学不稳反而帮倒忙。GRPO 的思路是“砍掉 Critic”。它对同一个 prompt 采样 G 条 response用这组样本内部的相对奖励做 Advantage 估计核心公式就是大家都熟悉的那一套A_i (r_i - mean(r)) / std(r)也就是说一条 response 好不好不需要和全局价值比只需要和同一 prompt 下其他兄弟样本比。这个计算量几乎为零而且天然抵抗奖励模型整体偏移——哪怕全局 reward 都膨胀了组内归一化之后照样有正有负梯度方向不会被带偏。我实测下来同样规模下 GRPO 的显存占用比 PPO 低 30% 到 40%训练吞吐能提升将近一倍这在 7B 以上模型上非常直观。1.2 三篇论文各自补了什么课这次评测主要围绕三篇论文展开论文核心任务共享的关键贡献DeepSeekMath数学推理正式提出 GRPO去掉 Critic用组内相对优势SimpleRL基础模型直接 RL证明可以不经过 SFT 直接强化训练给出温度调度思路DAPO系统化复现 RL 训练把解耦 Clip、动态采样、Token 级 Loss、过长惩罚四个技巧写成可复现方案DeepSeekMath 的价值是奠基GRPO 第一次让 LLM 团队在有限 GPU 条件下跑得动大规模策略优化。SimpleRL 比较激进直接拿基础模型开练对“SFT 是不是 RL 前置条件”给出了否定答案同时也带火了动态温度和逐步放长上下文这两个技巧。DAPO 则更像是工程手册它解决的问题是“为什么我复现 DeepSeekMath 时熵崩得那么快”、“为什么全对全错样本会让训练失效”把社区里靠感觉调的部分参数给形式化了。这里要说明一下 40 万 GPU 时的口径它不是单篇论文的消耗量而是我们评测时参考的真实规模调度——Tülu 3 团队在复盘文章里公开过类似量级的 A100 GPU 时消耗。把这 40 万 GPU 时摊到三篇论文的方法论和复现实验里很多小样本下看不出来的技巧差异会被放大得很清楚这也是我敢写这篇评测的原因。2. 十余项 GRPO 训练技巧实测拆解2.1 采样与数据侧好样本是一切的前提技巧 1提示集难度分层与过滤。GRPO 对 prompt 质量非常敏感。我踩过的坑是拿一版不太干净的数学题集直接跑里面很多题模型看一眼就能答对。全对组会产生一个问题同一组里所有 response 的 reward 相同Advantage 全为 0这一组样本对训练没有任何贡献白白消耗 GPU。反过来全是模型答不出来的题也会让梯度被噪声主导。实操上我会对 prompt 先做一次小成本预跑拿当前策略采 32 条 response统计每道题的正确率。正确率在 0% 到 30% 的题是最佳训练样本正确率超过 50% 的基本属于“记忆题”可以降权或换掉。这个过滤操作的成本是一次推理但对训练收益的影响非常直接。技巧 2采样数量 n 的设置。GRPO 里 G 值每个 prompt 采样的 response 数是个关键参数。DeepSeekMath 在部分任务上用过较大的采样量但社区实测下来G 在 16 到 32 之间收益比较明显再往上走效果提升很平缓而生成成本是线性增长的。我用 7B 模型做过对照G8 时 Advantage 方差偏大训练曲线抖动明显G16 时稳定很多G32 时曲线更平滑但要付出双倍生成开销对最终 pass1 的提升只有一两个点。所以我的默认建议是从 G16 起跑如果显存和算力紧张可以降到 8但要做好训练波动的心理准备。不要一开始就堆 64那是大算力团队压榨最后几个点才做的事。技巧 3动态温度与退火。SimpleRL 让我印象最深的点是把“温度”从一个生成参数变成了训练策略参数。模型在 RL 初期如果采样温度太低很快会陷入贪婪解码多样性不足熵迅速下降温度太高生成的文本乱得没法看reward 基线被拉低学习信号变差。推荐做法是温度从 1.0 起步随着训练进度缓慢升高到 1.2 甚至 1.5。更稳的变体是根据熵反馈动态调温维护一个 EMA 熵目标比如 0.5如果当前熵低于目标温度上调 0.05高于目标温度下调 0.05。这个自适应机制比固定温度表好使尤其是在提示集难度不均的时候。技巧 4最长长度分阶段提升。一开始就把 max_length 设成 4096会带来两个问题第一生成阶段很慢大部分样本其实用不了那么长白白浪费 GPU第二模型会在超长输出的边缘疯狂试探过早出现长度坍缩。DAPO 实验里明确提到了过短响应和过长响应之间的平衡问题。我的做法是分阶段先用 max_length1024 跑通训练流程等 reward 开始上升后再提到 2048最后再放 4096。每提升一次相当于给模型一次“能力解锁”它不会从一开始就学会偷懒用短答案终结。配合下一节要说到的过长惩罚这个技巧能明显拉高最终 response 的平均长度和质量。技巧 5全对/全错样本动态过滤Dynamic Sampling。DAPO 里我评价最高的一招。一个采样组如果全部对或全部错Advantage 计算出来全是零或全是噪声这一整个组的 loss 对策略优化没有意义。尤其全对组出现频率高的早期阶段训练会越跑越慢感觉像“卡住了”。实现上就是在每个 step 算完 reward 之后把每组的 reward 去重如果组内 reward 只有一种取值就把这组样本 mask 掉不参与后续 loss 计算。这个操作几乎零成本代码改动不超过十行但能有效防止资源浪费也缓解熵塌缩。2.2 算法与损失侧动手改损失之前先想清楚技巧 6解耦 ClipClip-Higher。传统的 PPO/GRPO clip 目标会把 ratio 限制在 [1-ε, 1ε] 区间内。DAPO 指出这个“一刀切”限制了高奖励样本的更新幅度当一条 response 的 reward 远高于组内平均时它的 ratio 可能会被上限 1ε 死死卡住梯度消失模型学不到任何东西。解耦 Clip 的做法是正 Advantage 的样本只设上限、不设下限——ratio 可以放大到 1ε 以上继续提供梯度负 Advantage 的样本只设下限、不设上限——ratio 缩到 1-ε 以下也照样更新。我看过不少人把这个技巧当成锦上添花但实测没有这个处理7B 模型在 200 到 400 步就会出现熵崩塌生成结果千篇一律加上之后训练能稳定推进到 1000 步以上。强烈建议所有 GRPO 实验默认打开。技巧 7Advantage 归一化的细节。组内标准化虽然是 GRPO 的招牌但有个容易忽略的工程细节std(r) 接近 0 的时候比如全对全错组除法会放大噪声甚至产生 NaN。除了用上面的动态采样过滤掉这种组归一化时还要加一个小 epsilon比如 A_i (r_i - mean(r)) / (std(r) 1e-6)。另外有一个可选的扩展如果任务奖励方差特别大可以在组内归一化之后叠加一个 ESMA reward 基线做二次平滑。GRPO 本身没有 Critic但并不意味着不能用滑动平均做高方差抑制。不过注意不要把均值法做得太重否则会削弱 group advantage 的即时性。技巧 8Token-Level Loss vs Response-Level Loss。DAPO 的 token-level loss 是我这次评测里收获最大的点。默认实现的 loss 一般以 response 为单位求平均这会导致短答案的 token 被赋予更高权重模型倾向于用简短回应拿奖励。token-level loss 则是把所有 token 一视同仁用总 token 数做分母。效果是长、短回答对梯度的贡献和它们的实际 token 数成正比模型不再“偷长度”。这个改动需要处理 mask 和分组索引稍微麻烦一点但收益很实在。我在评测中对比过同一配置response-level 跑出来的平均回答长度在 300 到 400 tokentoken-level 能稳定在 600 以上而最终正确率还略高。技巧 9KL 惩罚系数与参考模型 logp 缓存。GRPO 里 KL 的作用是防止策略模型跑飞但 β 系数不是越大越好。早期训练如果 β 过大模型稍微偏离参考模型就被拉回去探索受限β 太小则策略可能在一个 step 内跳太远reward 骗到手但生成质量崩掉。社区常见初始区间是 0.001 到 0.01DeepSeekMath 原论文用了相对小的系数SimpleRL 甚至考虑过完全关掉显式 KL靠采样温度和动态过滤来控制稳定性。我的建议是先按 0.01 起跑观察 KL 曲线的绝对值如果每个 step 的 KL 超过 1.0就调低学习率而不是猛加 β。工程上KL 计算依赖参考模型 logp。参考模型在整个训练过程中权重不变我们可以把每条 response 的 ref_logp 一次性算好缓存到磁盘训练时直接读取省掉一半前向计算。这个技巧 DAPO 和 Salsa 都有用到。注意缓存文件会很大——每个 token 一个 float几百万条样本就是几十 GB——但对 GPU 的节省是实打实的。技巧 10熵监控与干预。我建议你把熵当成和 loss 同等重要的核心指标。GRPO 训练前几百步熵快速下降是正常的但掉到 0.1 以下就要警惕再往下就是“死训练”——模型开始输出重复文本reward 曲线可以骗人但熵不会。一种干预手段是设置熵阈值低于阈值时自动调高温度更粗暴的是直接把最近一个 buffer 清掉重新采样。我在评测中发现熵掉到 0.05 之后再想救回来非常费劲与其事后补救不如事前监控。2.3 工程与调度侧吞吐和稳定的平衡技巧 11微批次与梯度累积。RL 训练里“生成”和“更新”是两个完全不同的环节。生成阶段建议用较大的 batch、哪怕多占点显存更新阶段的 micro-batch 则要克制一点。micro-batch 太大会让单步梯度方差偏大梯度范数抖动特别明显。我的经验是更新阶段的 micro-batch 控制在角色模型可接受的单卡 batch 的 50% 左右通过梯度累积凑到全局 batch。另外梯度裁剪在 GRPO 里比 PPO 更关键。原论文和主流实现默认梯度裁剪在 0.5 到 1.0 之间遇到 loss 突然跳高时优先检查是不是裁剪阈值被调窄了。技巧 12学习率调度。RL 后训练不要照搬预训练的 cosine 衰减。GRPO 没有一个明确的收敛 epoch长期处于探索状态如果按照预定 step 把学习率衰减到接近 0后期模型基本失去探索能力。正确做法是 constant 短 warmupwarmup 占整体 step 的 1% 到 3%之后保持恒定如果后面想微调收敛再做最后一小段线性衰减。技巧 13Overlong Reward Shaping过长惩罚平滑。这是 DAPO 的另一个实用技巧。很多实现会直接截断超过 max_length 的生成但“硬截断”会让模型学到在临界长度附近提前终止结果就是回答变得虎头蛇尾。DAPO 的做法是对超长 token 给一个平滑的负奖励比如超过 max_length 之后每多一个 token 扣一点分直到标记截断。这样模型接受到的信息是“太长了不好”而不是“长到某个数值就一切归零”。我实测这个技巧对最终回答质量的提升非常明显尤其是需要长推理链的数学代码类任务。如果不做平滑你能看到 response 长度分布死死贴在 max_length 边界上做了平滑之后长度分布才拉开真正的长推理样本才能涌现。技巧 14Off-policy 数据清理与刷新。GRPO 通常用一个 buffer 保存最近几轮的 rollout 数据。旧策略生成的数据如果隔太久再喂给新策略Advantage 和 KL 都会失真。我的经验是最多保留两轮生成数据超过之后直接丢宁可少吃数据也不要吃脏数据。某些开源代码为了吞吐开了很大的 replay buffer评测下来收益是负的。技巧 15必须盯死的 5 个监控指标。entropy正常区间 0.1 到 1.0过低预警。clip fraction被 clip 的 token 比例5% 到 15% 算正常过高说明策略跳太快。response length走均值曲线缓慢增长是好事暴跌或贴上限都是问题。grad norm稳定在 0.1 到 1.0 之间为佳突变伴随 loss 异常。reward 分布除了看均值还要看每组内 std全 0 或全满要检查数据。3. 40 万 GPU 时花在哪、怎么省3.1 算力分布生成是大头很多人以为 GRPO 贵在策略更新实际上贵在采样。一次训练 step 中Actor 需要为每个 prompt 生成 G 条 response这个阶段占掉的算力可以高达单 step 总消耗的 80% 以上。更新阶段的损失计算相对便宜毕竟只有一次前反向。用一个粗略的体感数字来说明如果提示集是 10 万条 promptG16每条 response 平均 2000 token那么一个 step 总共要生成 3.2 亿 token。这相当于一次中等规模的预训练数据采集——而在 GRPO 训练里这种生成每十几步就要做一遍。把这个体感乘以 40 万 GPU 时你大概能理解为什么采样技巧会比损失函数技巧更容易拉开算力差距。3.2 技巧的算力性价比我把评测里的技巧分成三档档位技巧额外算力成本收益类型零成本Dynamic Sampling、解耦 Clip、Token-Level Loss、Overlong Shaping、ref logp 缓存、熵监控几乎没有都是代码改动稳定性与最终质量低成本提示集预跑过滤、温度调度、长度分阶段、梯度累积调整一次推理评估或少量参数扫描训练效率高成本增大 G、放大模型、扩大提示集、放长 max_length线性到超线性增长状态上限建议所有新项目先把零成本那一排全部打开再考虑低成本项。我见过太多团队一上来就把 G 从 8 调到 32花了两倍算力结果因为没开 Dynamic Sampling大量样本被浪费效果反而比小 G 更差。3.3 小规模团队如何低配复刻40 万 GPU 时听起来吓人但那是包括多次消融实验、超参扫描和失败尝试在内的总量。如果目标只是把 GRPO 跑通并拿到稳定收益预算可以压缩到百分之一甚至更低。我建议小规模团队按这个路径走先用 7B 或 8B 模型、5000 到 10000 条高质量 prompt、G8、max_length1024把整体管线跑通。打开零成本技巧观察熵和 reward 是否稳定再决定要不要把 G 提到 16。用 8 卡 A100/H100 集群这样的配置一个实验大约几百到上千 GPU 时完全可承受。很多时候“技巧”的效力是给预算有限的人准备的越是在算力上输不起越要吃透上面那排零成本项。4. 可直接抄作业的 GRPO 基线配置4.1 推荐超参速查表下面是我评测下来最稳、最能出效果的默认配置适用 7B 到 14B 模型、数学或代码类任务。参数推荐值备注G采样数16算力紧张可降到 8温度1.0 起步动态升到 1.2~1.5结合熵反馈max_length1024 - 2048 - 4096分阶段提升Clip 上界1.2解耦 Clip正 Advantage 只设上限Clip 下界0.8负 Advantage 只设下限KL 系数 β0.001 ~ 0.01观察 KL 值调整学习率5e-7 ~ 1e-6warmup 1%~3%之后恒定梯度裁剪1.0loss 异常时优先检查batch size512 ~ 1024按提示集算需要配合梯度累积优化器AdamWβ(0.9, 0.95)权重衰减 0这套配置直接跑正常情况下 200 步之内能看到 reward 曲线明显上升熵在 0.3 到 0.8 之间波动response 长度缓慢增长。4.2 核心训练循环伪代码这里给一个简化版伪代码帮你理解核心逻辑怎么串起来。for step in range(total_steps): # 1. 采样 prompts sample_prompts() responses actor.generate(prompts, temperaturetemperature, max_lengthcur_max_len) # 2. 奖励与 Group Advantage rewards reward_model(prompts, responses) advantages group_normalize(rewards) # 加 epsilon 防除零 # 3. Dynamic Sampling过滤全对/全错组 mask group_reward_diversity_mask(rewards) responses responses[mask] advantages advantages[mask] ref_logp load_cached_ref_logp(responses) # 提前算好缓存 # 4. 策略损失Token-Level 解耦 Clip logp actor.compute_logp(responses) ratio exp(logp - ref_logp) clip_loss decoupled_clip_loss(ratio, advantages, eps0.2) # 5. KL 惩罚与熵目标 kl exp(ref_logp - logp) - (ref_logp - logp) - 1 loss clip_loss beta * kl # beta 可按 KL 趋势调整 # 6. 更新与监控 loss.backward() clip_grad_norm(1.0) optimizer.step() log(entropy, clip_fraction, response_length, grad_norm)4.3 上线前的最小验证清单跑大批量之前先用小规模数据检查这几件事100 个 prompt、G4、100 步以内能不能正常走完采样-奖励-更新循环ref_logp 缓存读写是否正常会不会文件太大导致 IO 成为瓶颈Dynamic Sampling 开启后mask 比例是否合理一般 10% 到 30%熵有没有在 100 步内崩到 0.1 以下reward 分布是否合理如果前 50 步就满分为常见情况优先回头查奖励模型。5. 常见问题与排查技巧实录5.1 问题速查表现象可能原因排查方向熵快速跌到 0.05 以下温度太低、未开解耦 Clip检查 Dynamic Sampling 和解耦 Clip配合温度反馈loss 突然 NaNlogp 数值溢出、KL 变成 inf用 fp32 计算 logp 和 KL检查梯度裁剪reward 长期不涨prompt 太难、奖励模型饱和换提示集难度分层看单组 reward 分布生成长度坍缩到几十 token硬截断过长输出换成 Overlong Reward ShapingOOM生成阶段 batch 过大生成和更新分开设 batch开 ref logp 缓存clip fraction 长期高于 30%学习率过高、β过小学习率减半观察 KL 曲线输出大量重复循环熵过低、温度被压死加大温度清理低质量 buffer5.2 三个真金白银的教训第一个教训是不要拿 PPO 的经验直接套 GRPO。我第一版实验照搬 PPO 的 reward shaping什么“多次惩罚”“格式惩罚”都往奖励里堆结果 Advantage 分布被搅得乱七八糟训练直接不收敛。GRPO 本身用组内对比已经抵消了大量 reward 偏移奖励设计越干净越好规则奖励的权重应该远低于验证器输出的自然信号。第二个教训参考模型的 logp 缓存一定要用高精度存储。训练通常跑 bf16但缓存 ref_logp 时用 bf16 会引入微小误差这些误差在 KL 计算里会被放大导致训练后期 loss 抖动。我觉得这种问题不值得花时间去排查直接 fp32 落盘省心。第三个教训别迷信大 G。我做过 G64 的实验gpu 时成本翻了四倍最终效果和 G16 Dynamic Sampling 的版本基本持平。RL 的收益瓶颈经常在数据多样性和奖励信号而不是采样数量本身。先把免费的技巧吃透再考虑砸算力。5.3 网格搜索的三个经验法则如果你需要调参我建议用下面的顺序先调温度相关参数再调 clip 上下界最后动 KL 系数。原因很简单温度影响探索范围是稳定性的根基clip 上下界影响每一步的可更新幅度比 KL 更直接KL 系数在训练中后期影响策略漂移前期调了往往白调。调参时每次只动一个变量跑至少 100 步再判断。GRPO 训练前期噪声很大50 步内的曲线对比经常误导人我吃过这个亏——所谓“A 配置比 B 配置强”很可能只是随机误差。至少跑到 200 步对比 3 次不同随机种子的均值再下结论。最后再分享一个我自己的习惯在我把所有零成本技巧打开之前是不会碰高成本参数的。GRPO 这套东西稳定性做扎实之后奖励曲线会自己往上涨稳定性没做好之前堆多少算力都像是在往漏水的桶里倒水。先在 8 卡环境里把熵、clip fraction、动态采样这几个指标摸熟再去追逐 40 万 GPU 时量级的效果你会少走很多弯路。这个系列后面如果有时间我会把奖励模型漂移和 GRPO 的组合拳单独写一篇那是另一个大坑。