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.
结论
在 SAC
g1_motion_tracking、8192 envs 下,相对优化前 commit:update_state从 29.147 ms 降至 19.230 ms,节省 9.917 ms / 34.0%,即 1.52×;完整env.step下降 10.7%。update_state从 28.150 ms 降至 17.801 ms,节省 10.349 ms / 36.8%,即 1.58×;完整env.step下降 18.1%。update_state中两次 refresh 都受益:分别节省约 6.07 / 6.62 ms。termination/anchor_pos的完整 wrapper 看起来有 8–10× 加速,但不能把这个数字归因于 termination Numba 算术。它是本轮执行顺序中第一个读取 robot body state 的 term,因而把第一次 full-batch refresh 记在了自己名下;扣掉 refresh 后没有观察到独立、显著的 termination 算术收益。update_state约 6–7%,继续微调它们已经不是最优杠杆。剩余主要瓶颈转移到 command transform、observation 后处理,以及 MuJoCo 的 physics。本文的精细复测与 PR #1314 中 collector benchmark 的统计口径不同:这里报告
NpEnv.step内置阶段计时的“三轮 step median 再取 median”;PR body 报告 benchmark 脚本的 run mean 与 env/s。因此两组数值不应逐项混用。阶段与端到端 A/B
update_state前 → 后update_state收益env.step前 → 后env.step收益reset_done前 → 后reset_done基本不变,符合本轮修改集中在正常 step 热路径的预期。上表为无 Python term wrapper 的独立运行,避免 profiler 自身改变 canonical 阶段结果。三次无埋点独立运行的原始 per-run median
update_stateenv.stepreset_doneupdate_stateenv.stepreset_done完整热点 term A/B
这里的“完整 term”是一次完整的
term_cfg.func(...)调用,不只计 Numba kernel:它会包含该调用触发的 getter/cache refresh、body subset copy 和 kernel;不包含 manager 通用的 shape/finite 检查、weight 与聚合。每轮取 100 次调用的 mean,再取三轮 median。termination/anchor_posreward/motion_body_posreward/motion_body_orireward/motion_body_lin_velreward/motion_body_ang_veltermination/anchor_posreward/motion_body_posreward/motion_body_orireward/motion_body_lin_velreward/motion_body_ang_vel聚合结果:
收益归因:为什么
anchor_pos的 8–10× 不是 termination kernel 的 8–10×termination/anchor_pos恰好是第一个访问 motion command robot body cache 的 term。完整 wrapper 的计时因此包含第一次 full-batch body-state refresh。用同条件的 100-step diagnostic run 把 refresh 再分成first_read与force后得到:anchor_poswrapper 扣除首次 refresh 后扣除值只是两个嵌套
perf_counter_nswrapper 的差值,不适合作为微基准;它只用于确认量级。证据说明anchor_pos的绝大部分表观下降来自 fused refresh,不能据此声称 termination 算术本身 8–10×。若要单独判断这个极短 kernel,需要专门的 kernel microbenchmark;它不会改变本帖的完整 term 与阶段结论。每个正常
update_state实际发生两次有效 refresh:首次读取一次,以及command.post_compute(force=True)一次。三轮埋点结果按每步折算为:因此,四个 rewards 的约 4 ms 与 fused refresh 的约 6–7 ms,基本解释了
update_state的约 10 ms 端到端下降。注意首次 refresh 已经包含在anchor_pos完整 wrapper 中,不能再把“五个目标 term 节省”和“两次 refresh 节省”直接相加,否则会重复计数。当前剩余瓶颈
以下为优化后完整 manager callable 的 coarse instrumentation;占比以无埋点
update_statemedian 为分母,因此只应按量级读,不应把各 wrapper 小数位当成无扰动真值。update_state分区command_manager.computecommand_manager.post_computeobservation_manager.compute进一步拆分:
post/copy/noise/isfinite/concatresidual 约为 3.46 / 3.04 ms,所以继续逐个优化 getter 的上限较低。command.post_compute的第二次 fused copy 已只需约 0.28–0.33 ms;剩余约 3.9 ms 主要是 relative transforms / body-frame 转换。update_state约 6.3% / 6.7%。在有限改动范围内,这一组已不再是首要优化对象。env.step中,MuJoCo 最大单项仍是 physics,优化后约 49.10 ms;MJWarp 的主要分区为update_state17.80 ms、reset_done14.69 ms、physics 13.57 ms。下一轮若继续优化,优先级应是 command transform、observation 的通用 post/concat pipeline;MuJoCo 若追求更大的完整 step 收益,则 physics 端的杠杆更大。它们是新的 scope,不属于 #1304 的五个 term/body-state copy 收敛。
精确复现信息
A/B commits
d95c85f0b782f59e0174d93e4f7c21aa46b58f7a9cca010d2c97910a6704a3da80b0d7f347103591优化后分支为
dev/issue-1304-motion-numba-body-state,目标分支为dev/issue-1042-manager-based-api;截至本帖创建时 PR #1314 仍等待 maintainer 审批和手动 merge。硬件 / 系统 / runtime
yves-9950x3d27.0.0-30-genericx86_64NUMBA_*、OMP 或 BLAS thread 环境变量;优化后代码默认workqueuethreading layer、8 threadsMJWarp 在上述 RTX 4090 上运行;Numba rewards 与 fused host-copy 是 CPU 路径。复测时建议固定 CPU governor、关闭其他重负载并记录温度/频率;跨机器绝对耗时不能直接比较,A/B 应在同一台机器、同一依赖环境中完成。
Workload 与统计规则
conf/sac下task=g1_motion_tracking/{mujoco,mjwarp};通过正式 backend owner 选择后端,不用training.sim_backend单独切换。num_envs=8192。env.seed=123;random action RNG seed20260826,action 范围[-1, 1],float32。env.init_state();profiler wrapper 在 init 之后安装,因此初始化与 Numba 编译不进入统计。update_state_ms/env_step_total_ms/reset_done_ms直接读取NpEnv.step已有的perf_countertiming。update_state当成阶段 A/B。复跑命令
先准备两个 worktree,并用优化后的 lock/extras 建立一套共同依赖环境。
PYTHONPATH强制每次加载指定 worktree 的src,--no-sync防止在切换 A/B 源码时重写环境。把下方两个折叠块分别原样保存为
/tmp/profile_update_state.py和/tmp/aggregate_update_state.py,然后运行:Profiler SHA-256:
7de572e10c83af040b4bb08f2824ce95dfc48124cf890192b2b9fdc143233386Aggregator SHA-256:
500d5f239782776013611fd4224c2166ac8df76af26907efc7259cd8f958dea0建议同时保存以下命令输出,便于判断跨机器差异:
下面嵌入本次实际使用的脚本;脚本只做 runtime wrapper,不修改仓库源码。
/tmp/profile_update_state.py(点击展开)/tmp/aggregate_update_state.py(点击展开)All reactions