You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
摘要
这个问题表面上是“rollout 要不要把 actor D2D 一遍”,实际包含两个独立问题:
结论是:
self.actor,不需要常规 actor 参数拷贝。target critic用于 bootstrap 稳定性,不是 rollout actor,也不意味着需要target actor。本文只做理论澄清和当前代码审计,不提出新的 execution path,也不在缺少 benchmark 的情况下主张替换 UniLab 的同步协议。
一、理论上:行为策略、当前策略和目标网络是三件事
记:
μ:执行 rollout、生成 transition 的行为策略;πθ:learner 正在优化的当前 actor;Qφ̄:用于 critic bootstrap 的 target critic。Replay buffer 中的 transition 可以来自历史策略:
SAC 更新 critic 时,stored action
a来自 replay;bootstrap 的 next action 则由当前策略采样:因此 SAC 不要求
μ与当前πθ完全相同,也不要求每做一次梯度更新就立刻阻塞所有 collector。Replay 本身就包含多版本行为策略产生的数据。但 policy lag 仍然会改变数据分布。滞后过大时,可能出现:
所以同步频率是吞吐、策略新鲜度和一致性之间的工程权衡,而不是“off-policy 所以永远不用同步”。
二、什么时候需要 actor 副本
关键判断不是“是不是 off-policy”,而是:参数存储是否由 rollout 和 optimizer 共同拥有。
三、Holosoma FastSAC 代码审计
审计基线:
amazon-far/holosoma@6e146b0。1. Rollout 与优化器是同一个 actor
在 setup 中,actor 直接创建在训练 device 上;随后:
证据:
fast_sac_agent.py#L266-L332。self.policy是self.actor.explore的绑定方法,而 optimizer 持有同一个self.actor.parameters()。这里没有第二个 rollout actor。2. 每轮先 collect,再更新;下一轮自然看到新参数
训练循环先在
torch.no_grad()下调用policy(...),执行一个 vectorized env step并写入 replay,然后执行若干 critic/actor updates:证据:
fast_sac_agent.py#L650-L775。由于 collect 和 update 串行访问同一参数存储,下一轮 rollout 自动读取更新后的 actor,不存在“learner actor 再拷给 rollout actor”的步骤。
Rollout 使用的是 SAC 随机策略而非确定性均值,且
explore本身带@torch.no_grad():fast_sac.py#L125-L146。3. 有 target critic,没有 target actor
Holosoma 创建并 Polyak 更新
qnet_target,但没有为 rollout 创建 actor target/snapshot。这个 target critic 只服务 Bellman bootstrap:fast_sac_agent.py#L303-L317、fast_sac_agent.py#L770-L774。4. 多 GPU 也不是每轮复制 rollout actor
每个 rank 在本地 GPU 上持有 actor 和环境。初始化时从 rank 0 broadcast 参数,训练时 all-reduce gradients,各 rank 的 optimizer 随后得到一致更新:
fast_sac_agent.py#L354-L401。因此它是同步数据并行下的本地共享 actor,不是独立 actor-learner 系统中的周期 D2D rollout replica。
四、UniLab 当前实践:独立 collector 必须同步 actor
审计基线:
unilabsim/UniLab@e326847。UniLab 的架构边界与 Holosoma 不同。
1. Learner 建立版本化 shared-memory snapshot
DoubleBufferOffPolicyRunner根据 learner actor 的 state dict 建立SharedWeightSync,然后 spawn 独立 collector:double_buffer_runner.py#L264-L266double_buffer_runner.py#L324-L361因此 collector 不可能直接引用 learner 进程中的 Python actor 对象。
2. Collector 构造自己的 actor
Collector 在
collector_infer_device上重新构造 actor,并从 snapshot 加载初始权重:worker.py#L282-L315。运行中它检查 snapshot version;发现新版本后才 apply 到本地 actor:
worker.py#L343-L359。所以 UniLab rollout 使用的是
collector_actor(version=v),而不是 optimizer 正在原地修改的learner.actor。3. 权重在 learner 更新后发布
Learner 完成一轮 critic/actor updates 后调用:
证据:
double_buffer_runner.py#L626-L699。sync_collection控制 collector/learner 的阶段协调;它不表示双方共享同一个 actor 参数对象。Double buffering 仍允许 collection 与 learning 重叠,因此也不应把它简单理解成“每一个 action 都严格使用刚完成的 learner update”。4. 当前传输路径不是直接 D2D
SharedWeightSync.write_weights对 learner tensor 执行detach().cpu().numpy(),写入 CPU shared memory:weight_sync.py#L64-L86。CUDA collector 使用持久化 pinned-host/device staging:先复制 shared-memory snapshot,再做一次 flat H2D,最后在设备内 apply 到 actor tensors:
weight_sync.py#L161-L232。因此当前路径可概括为:
如果 collector 在 CPU,则是 shared-memory 到 CPU actor 的 copy;如果 collector 在 accelerator,则存在 H2D。是否值得改成 CUDA IPC、P2P 或其他路径,必须由 profile/benchmark 证明,不能仅凭“看起来多拷了一次”下结论。
默认 SAC 配置选择 accelerator collector、
env_steps_per_sync: 1:conf/offpolicy/algo/sac.yaml#L1-L23。五、直接回答原问题
self.actor对象六、对 UniLab 的建议
这次审计没有发现“理论上必须改成共享 actor”这样的结论。相反,当前 actor replica 是独立进程 contract 的自然结果。更值得明确的是可观测性和术语:
learner actor、collector actor replica、target critic。sync_collection是阶段调度语义,不是参数对象共享或零 policy lag 的承诺。published_policy_version、collector_policy_version、version lag 和 weight-sync wall time。希望后续讨论聚焦两个可验证问题:当前训练中 policy-version lag 的实际分布是多少,以及 weight sync 在端到端 step time 中占比多少。二者都应先测量,再决定是否需要架构变化。
All reactions