背景
FastSAC 异构训练器(motrix_rl/fastsac/async_impl)目前只支持 1 collector × 1 learner:
SharedTransitionRing 是 SPSC(单生产者单消费者)有界背压环;
WeightSnapshot 的 seqlock 双缓冲建立在「每个共享量只有一个写方」的前提上;
- 设计文档(
wiki/design/fastsac-async-heterogeneous-trainer.md)明确写了「当前只支持 1 collector × 1 learner、单机」。
在多 NUMA node 的服务器 CPU 上,单个 collector 进程存在两个问题:
- 跨 NUMA 内存访问:collector 进程的环境状态、transition staging buffer、pinned host buffer 若分配在远端 NUMA node,采样吞吐显著下降;OS 调度器还可能把进程在线程间迁移,导致本地性反复失效。
- 单 collector 无法吃满多路 CPU:collector 的 env step 是纯 CPU 负载,单进程受单进程调度与单 NUMA node 内存带宽限制,无法利用其余 node 的核心,喂不满 learner(
learn_pct 偏低、ring 断粮)。
需求
在训练配置中支持启动 多个 collector 进程,并将每个 collector 绑定(affinity)到不同的 NUMA node:
- 新增配置项,例如
async_options.num_collectors 与每个 collector 的 NUMA/CPU 绑定(如 numa_nodes: [0, 1] 或 cpus_per_collector),默认行为保持单 collector、不绑定(向后兼容)。
- 每个 collector 负责一部分 env(
num_envs 按 collector 切分),各自进程内做 numactl 等价的 memory policy 绑定与 CPU affinity(os.sched_setaffinity + NUMA memory binding)。
- 权重发布从「learner → 单 collector」扩展为「learner → N 个 collector」广播(每个 collector 一份独立
WeightSnapshot,learner 逐份非阻塞 publish)。
- transition 通道:每个 collector 一条独立 SPSC ring(不做共享 MPSC 环),保留有界背压语义;learner 轮询多路 ring,聚合后大批量
.to(device) 上 GPU。
- seed 按 collector 划分(如
seed + collector_id),保证可复现且样本不重复。
StatsQueue、Control.collector_steps 等共享量适配多 collector 聚合;TensorBoard/控制台的 collector timing 指标按 collector 分列或聚合。
- resume / checkpoint 契约需要明确多 collector 下的语义(首版仅支持 resume 时重新 reset env,需在契约中写明)。
设计方向(吞吐优先,learner_bound)
核心原则:learner 的 GPU 永不因数据断粮空转,collector 全速自由跑,一切同步点允许松弛。
- 拓扑:每 NUMA node 一个 collector,每 collector 独立 SPSC ring + 独立
WeightSnapshot + 独立 step 计数器;现有无锁原语(单写方 cursor、seqlock)不改。
- learner 也绑 NUMA:绑定到 GPU 所在 node(PCIe 本地),drain 时跨 node 读 ring 无法避免,但 replay buffer 与采样索引保持 node 本地。
- 背压按 ring 独立:快的 collector 阻塞在自己的满环上,不拖住别人;ring 全空时 learner 不等待,在已有 buffer 上继续
num_updates。
- 权重发布:异步、非阻塞、允许逐份跳过(seqlock odd 时下轮再发);staleness 作为被监控指标(
async/policy_lag 按 collector 分列),不做版本对齐屏障。
- 数据顺序无关:off-policy + i.i.d. 采样,多 collector transition 入 buffer 顺序无关,不需要全局序号。
- 明确不做:共享 MPSC 环 / 原子游标、collector 间同步、per-step 权重同步、多机。
collector 推理设备
多 collector 改变了 CPU/CUDA 推理的权衡(N 个 CUDA collector 会与 learner 产生 N 倍 H2D/D2H burst 争用;CPU 推理的吞吐损失比例也可能随 per-collector 核数变化)。此决策不预先锁定:
- 首版实现按当前默认:CUDA 推理(
collector_inference_device="cuda"),保持与现有单 collector 行为一致;
- 扩展
scripts/bench_fastsac_collector_inference.py 为多 collector 版本,用实测数据决定多 collector 场景下的默认值是否调整(比较「N × CUDA 推理吞吐 − N 倍 GPU 争用」vs「N × CPU 推理吞吐 + learner 无争用」)。
验收参考
- 在 2 NUMA node 服务器上,2 collector(各绑一个 node)相对 1 collector,
perf/env_steps_per_s ≥ 1.8×(扣除 drain 跨 node 拷贝开销);
perf/learn_pct 上升,逼近 GPU-bound;learner perf/updates_per_s 不因多 collector 下降;
- 单 collector 配置行为与现状完全一致(默认不回退、不改变现有指标);
strict 模式收敛曲线仍落在同步版 run-to-run 方差带内。
相关
- 设计文档:
wiki/design/fastsac-async-heterogeneous-trainer.md(§「非目标/约束」中单 collector 假设需同步更新)
- 性能分析:
wiki/research/fastsac-gpu-analysis.md
背景
FastSAC 异构训练器(
motrix_rl/fastsac/async_impl)目前只支持 1 collector × 1 learner:SharedTransitionRing是 SPSC(单生产者单消费者)有界背压环;WeightSnapshot的 seqlock 双缓冲建立在「每个共享量只有一个写方」的前提上;wiki/design/fastsac-async-heterogeneous-trainer.md)明确写了「当前只支持 1 collector × 1 learner、单机」。在多 NUMA node 的服务器 CPU 上,单个 collector 进程存在两个问题:
learn_pct偏低、ring 断粮)。需求
在训练配置中支持启动 多个 collector 进程,并将每个 collector 绑定(affinity)到不同的 NUMA node:
async_options.num_collectors与每个 collector 的 NUMA/CPU 绑定(如numa_nodes: [0, 1]或cpus_per_collector),默认行为保持单 collector、不绑定(向后兼容)。num_envs按 collector 切分),各自进程内做numactl等价的 memory policy 绑定与 CPU affinity(os.sched_setaffinity+ NUMA memory binding)。WeightSnapshot,learner 逐份非阻塞 publish)。.to(device)上 GPU。seed + collector_id),保证可复现且样本不重复。StatsQueue、Control.collector_steps等共享量适配多 collector 聚合;TensorBoard/控制台的 collector timing 指标按 collector 分列或聚合。设计方向(吞吐优先,
learner_bound)核心原则:learner 的 GPU 永不因数据断粮空转,collector 全速自由跑,一切同步点允许松弛。
WeightSnapshot+ 独立 step 计数器;现有无锁原语(单写方 cursor、seqlock)不改。num_updates。async/policy_lag按 collector 分列),不做版本对齐屏障。collector 推理设备
多 collector 改变了 CPU/CUDA 推理的权衡(N 个 CUDA collector 会与 learner 产生 N 倍 H2D/D2H burst 争用;CPU 推理的吞吐损失比例也可能随 per-collector 核数变化)。此决策不预先锁定:
collector_inference_device="cuda"),保持与现有单 collector 行为一致;scripts/bench_fastsac_collector_inference.py为多 collector 版本,用实测数据决定多 collector 场景下的默认值是否调整(比较「N × CUDA 推理吞吐 − N 倍 GPU 争用」vs「N × CPU 推理吞吐 + learner 无争用」)。验收参考
perf/env_steps_per_s≥ 1.8×(扣除 drain 跨 node 拷贝开销);perf/learn_pct上升,逼近 GPU-bound;learnerperf/updates_per_s不因多 collector 下降;strict模式收敛曲线仍落在同步版 run-to-run 方差带内。相关
wiki/design/fastsac-async-heterogeneous-trainer.md(§「非目标/约束」中单 collector 假设需同步更新)wiki/research/fastsac-gpu-analysis.md