perf(managers): Numba 热点、body-state 与 update_state 加速 (#1304, #1316) - #1314
Merged
TATP-233 merged 21 commits intoAug 27, 2026
Merged
Conversation
This was referenced Aug 26, 2026
…umba perf(managers): continue reducing update_state cost (#1316)
Multi-rank off-policy collectors pin their MuJoCo BatchEnvPool workers to a per-rank CPU block via EnvCfg.cpu_ids, but the collector's host-side compute did not follow: Numba's parallel kernels sized their pool from the host CPU count and drifted across rank boundaries, and the OpenBLAS pool spawned at import kept the host-wide mask. NpEnv.__init__ now applies apply_env_cpu_runtime(cfg.cpu_ids) on the cold path: the process is confined to the block (existing threads pinned individually via /proc/self/task, later threads — including Numba's lazily-launched pool — inherit the mask) and Numba's pool is sized to len(cpu_ids) unless NUMBA_NUM_THREADS is set explicitly. cpu_ids=None keeps the single-rank path bit-identical. Backend-agnostic: any env declaring cpu_ids (e.g. motrix once it grows affinity support) gets the same confinement.
…lock perf(env): confine DP collector host compute to the per-rank CPU block
perf(mjwarp): reduce g1 motion tracking reset latency
… probes (#1328) Diagnostic probes for the SAC/MuJoCo single-GPU collector CPU under-utilization report: pool thread-count scaling on the G1 scene, and per-phase wall/CPU attribution of a full task env step. New files only; no behavior change.
…hread-sizing benchmark(env): add MuJoCo pool thread-scaling and env-step phase-CPU probes (#1328)
os.sched_setaffinity/sched_getaffinity are Linux-only, so mypy on darwin rejected the direct attribute access (attr-defined) and the unit tests' monkeypatch.setattr/delattr failed because the attributes do not exist. Resolve the affinity symbols via getattr at call time (identical runtime semantics, still monkeypatchable) and pass raising=False to the test monkeypatch seams so they work whether or not the host exposes them.
fix(base): cpu_runtime 在非 Linux 主机上的类型检查与测试修复
Reward displays (tensorboard reward/mean and the terminal logger) lagged badly on off-policy and APPO runs: - collectors sent metrics only every num_envs * 10 env steps, so the reported reward changed just once per ~10 learner iterations; - runners then averaged the last 100 (off-policy) or 50 (APPO) reports, each already a rolling 100-episode mean, delaying the visible curve by ~1000 iterations. Report metrics every collector cycle, keep the runner-side window at the last 10 reports, and bound the per-worker episode reward/length buffers with deque(maxlen=100) instead of lists that grew for the whole run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ManagerBasedRlEnv.reset() replaced state.info["log"] with the reset-only extras (Episode_Reward/*), wiping the fresh per-step reward/* entries that _update_state_in_read_phase() had just computed for the current transition. On any step where at least one env resets — with thousands of envs, nearly every step — collectors therefore saw no reward/* keys at all, so the per-term reward components in tensorboard and the terminal logger stayed frozen at one stale value for thousands of iterations (observed as long flat staircases on reward/motion_* etc.). Merge instead of replace on the autoreset path: the pre-reset per-step entries stay, reset extras layer on top. Standalone (non-autoreset) resets are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(logging): make collector reward reporting timely
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
本 PR 现在集成两个已完成 roadmap 的有界工作:
termination/anchor_pos与四个固定reward/motion_body_*热点改为预热、并行 Numba kernels;通过正式SimBackend.copy_body_state_w()contract 消除四组 full-batch getter/gather;MuJoCo 与 MJWarp 共用 fused host-copy kernel。command_manager.compute、command_manager.post_compute、observation_manager.compute三个最大 manager 分区。Linked work
dev/issue-1042-manager-based-api的唯一最终 handoff。Manager-Based API contract boundary
本 PR 保留文档定义的 Manager-facing 公共边界:
motion_body_*reward 仍是四个独立 MBA term 和四个独立 Numba kernel,并未融合成一个不可配置的 reward;RewardManager仍逐项应用 weight 与 dt。termination/anchor_pos仍由TerminationManager聚合,并保留 bool shape/dtype 校验和 termination/timeout split。Entity/SimBackend.copy_body_state_w()contract 接入;task/env 不访问 MuJoCo 或 MJWarp 私有对象。ManagerBasedRlEnv、NpEnvState、reset/step 核心顺序和 runner/IPC 路径没有修改。以下是在本 PR 中明确披露的内部或 source-level 适配,不属于“所有实现细节完全不变”的声明:
bad_anchor_pos_z_only从 module function 改为ManagerTermBaseclass。Hydra/Manager 的 dotted callable 与(cfg, env)冷路径实例化兼容;旧式直接 Python 函数调用不再 source-compatible。MotionCommand构造冷路径会执行一次_update_metrics()以完成 kernel 预热,因此首次 reset 前的 metrics buffer 可以是已计算值,而不是历史实现的全零值。reset/step 核心调用顺序未改,但本 PR 不再把这一初始化细节描述为 lifecycle 完全无变化。workqueuethreading layer,并把 Numba worker mask 限制到最多 8 线程。用户设置的NUMBA_THREADING_LAYER/NUMBA_NUM_THREADS优先。因此,本 PR 的 compatibility claim 限定为 documented Manager-facing public boundary;内部 term 结构、buffer ownership、JIT/thread runtime 和数值执行属于明确 adaptation,数值、shape/dtype、body subset/order 与 output reuse 等近风险边界已有专项测试。
Final head and validation
4fa6631a3c9c465db86cd671275319168ce36fe0make test-all: passedRemote CI override: per the maintainer/user instruction for these non-main roadmap PRs, validation is local-only; remote CI is intentionally skipped and not awaited.
Performance: #1304 phase
Same host: AMD Ryzen 9 9950X3D2, NVIDIA RTX 4090 48 GiB, 8192 envs, warmup 10 / measure 100. Values below preserve the original #1304 collector benchmark convention (median of three independent run means).
Motrix intentionally has no performance result or accelerated support claim.
Performance: #1316 direct cumulative A/B
Fresh interleaved comparison of exact #1316 base
9cca010dagainst the final tree:g1_motion_tracking, 8192 envs, warmup 10, measure 100, fixed action/env seeds, three repetitions. Phase values are the median of three per-run medians; instrumented manager values are the median of three per-run means.command_manager.computecommand_manager.post_computeobservation_manager.computeupdate_statestep_coreenv_step_totalcommand_manager.computecommand_manager.post_computeobservation_manager.computeupdate_statestep_coreenv_step_totalThe isolated #1319 immediate-base A/B measured observation at -7.24% MuJoCo / -7.93% MJWarp. The direct roadmap-wide values are deliberately conservative; both methods agree on direction.
MJWarp PCIe accounting
backend_physics_msbackend_host_cache_refresh_msbackend_control_upload_msThe approximately 0.66 ms GPU-to-host copy and synchronization occur inside
backend.step(). They are already included instep_core_msandenv_step_total_ms, remain outsideupdate_state, and are not double-counted.Remaining bottlenecks
At the final head, the largest measured
update_statepartition isobservation_manager.compute(MuJoCo/MJWarp 4.20/3.58 ms), followed by complete reward+termination term calls (2.94/2.62 ms) andcommand_manager.compute(2.11/1.75 ms).command_manager.post_computeis now 0.71/0.59 ms. At whole-step scope, backend physics dominates; MJWarp's stable 0.66 ms D2H barrier is part of real collector cost.Impact
update_statecost is lowerChecklist
make test-all