现象
g1-wbt-dance 异步训练(2048 envs, strict UTD, num_updates=4, batch 8192, 单卡 RTX 4090)进入稳态后:
- collector
wait ~1.3ms(ring 趋满)→ learner 是慢的一侧
- learner 面板:
update 132ms(= drain 到 8 batch × 4 updates 的总耗时),drain 5.75ms,ring/gate wait <1ms —— learner 看起来满载
- 但
nvidia-smi 观察 GPU util < 50%
已确认的事实
- update 本身是算力瓶颈,不是 launch 间隙:单独连续跑
agent.update(4)(无 collector/drain)实测 GPU 85-100% util、359W/450W、2745MHz 满频,3.2-3.7 ms/update sustained。
- collector CPU 侧 ~16ms/batch,learner
ingested × num_updates 次 update ≈ 16.4ms/batch,两边打平,吞吐由 learner wall time 决定。
- update 内部已 torch.compile + AMP,profiler 显示大头是 compiled fwd/bwd 和 fused adamw。
疑点
按循环解剖,learner 每 ~139ms 循环中 update 占 132ms(~95%)。update 期间 GPU 满载,那么稳态 util 理论上应 ≥ 85%,与观测的 <50% 矛盾 —— 存在未定位的 GPU 空闲间隙。
已排除/已知的间隙(worker.py learner 主循环)
| # |
间隙 |
量级 |
备注 |
| 1 |
drain() H2D:6 tensors × 8 slots 从 pageable 共享内存搬 GPU |
5.75 ms/循环 |
最大常态间隙,SM 空闲 |
| 2 |
idle_sleep(无 update 时睡 0.5ms) |
ring/gate wait 各 ~0.5ms |
|
| 3 |
publish_if_due 参数扁平化 + D2H |
~2.2ms |
|
| 4 |
日志窗口 float(v) 逐个物化 CUDA 指标 → 多次强制同步 |
每窗口若干 |
logging_interval 一次 |
| 5 |
面板渲染 + pynvml/psutil 采样 + TensorBoard add_scalar ×20-40 |
每窗口几 ms |
|
| 6 |
checkpoint torch.save(state_dict) |
周期性几十-几百 ms |
save_interval 一次 |
| 7 |
collector 与 learner 同卡 context 分时(未开 MPS) |
collector 每 ~16ms 插 1-2ms 推理 |
|
以上各项加总无法解释 95% update 占比与 <50% util 的落差。
待验证的方向
环境
- 机器:epyc-9004-gpu-1(192C / 2×RTX 4090 48GB)
- 分支:perf/console-env-step-substages(a1927ce)
- 任务:
task=g1-wbt-dance/motrix.fastsac num_envs=2048(默认 UTD 配置)
现象
g1-wbt-dance 异步训练(2048 envs, strict UTD, num_updates=4, batch 8192, 单卡 RTX 4090)进入稳态后:
wait ~1.3ms(ring 趋满)→ learner 是慢的一侧update 132ms(= drain 到 8 batch × 4 updates 的总耗时),drain 5.75ms,ring/gate wait <1ms —— learner 看起来满载nvidia-smi观察 GPU util < 50%已确认的事实
agent.update(4)(无 collector/drain)实测 GPU 85-100% util、359W/450W、2745MHz 满频,3.2-3.7 ms/update sustained。ingested × num_updates次 update ≈ 16.4ms/batch,两边打平,吞吐由 learner wall time 决定。疑点
按循环解剖,learner 每 ~139ms 循环中 update 占 132ms(~95%)。update 期间 GPU 满载,那么稳态 util 理论上应 ≥ 85%,与观测的 <50% 矛盾 —— 存在未定位的 GPU 空闲间隙。
已排除/已知的间隙(
worker.pylearner 主循环)drain()H2D:6 tensors × 8 slots 从 pageable 共享内存搬 GPUidle_sleep(无 update 时睡 0.5ms)publish_if_due参数扁平化 + D2Hfloat(v)逐个物化 CUDA 指标 → 多次强制同步torch.save(state_dict)以上各项加总无法解释 95% update 占比与 <50% util 的落差。
待验证的方向
nvidia-smi dmon -s u确认 util(排除观测时刻偏差:warmup/饥饿阶段 util 低是正常的).item()、metric 累计的 D2H)环境
task=g1-wbt-dance/motrix.fastsac num_envs=2048(默认 UTD 配置)