Skip to content

isaacgym / isaacsim / genesis 后端在多 GPU data-parallel 下所有 rank 挤在 GPU 0 #1508

Description

@TATP-233

问题

多 GPU data-parallel 训练时,isaacgym / isaacsim / genesis 三个 GPU 后端的 env(collector / worker 进程)全部落在可见设备 0,rank 到 GPU 的分配机制(training.devicesresolve_dp_rank_device)只作用于 learner / replay buffer,从不传给这三个后端的 env。对比:mjwarp 通过 bind_backend_process_devicesrc/unilab/base/process_device.py)强制 collector 与 learner 同卡,行为正确。

各后端证据

isaacgym(Python 3.8 子进程 worker + shm 协议)

  • owner YAML 写死 env.isaacgym_device_id: 0src/unilab/conf/ppo/task/g1_walk_flat/isaacgym.yaml:31src/unilab/conf/sac/task/g1_walk_flat/isaacgym.yaml:29EnvCfg.isaacgym_device_id 默认 None(src/unilab/base/base.py:57)。
  • 默认值链路:subprocess_ipc/backend.py:302 device_id = 0 if device_id is None → INIT payload 携带 device_id(:408)→ worker gym.create_sim(device_id, graphics_device_id, ...)isaacgym/worker.py:96-120)。
  • DP 下 env_cfg_override 只追加 cpu_idsuni_rl/offpolicy/double_buffer_runner.py:528-537),从不重写 isaacgym_device_id;worker 子进程只继承父进程 env,无人设 CUDA_VISIBLE_DEVICES

isaacsim(Kit 子进程 worker)

  • 链路与 isaacgym 同构:owner YAML 写死 env.isaacsim_device_id: 0src/unilab/conf/ppo/task/g1_walk_flat/isaacsim.yaml:27 等)→ 同一 payload 字段 → worker self.device = f"cuda:{device_id}"isaacsim/worker.py:152-158),传给 AppLauncher({"device": ..., "multi_gpu": False})SimulationCfg
  • 注:isaacsim/worker.py:115self.device = "cuda:0" 只是 _WorkerContext.__init__ 占位初值,init_sim 第一行即被 payload 覆盖,不是根因;根因是 payload 的 device_id 永远来自写死 0 的 YAML(或 None→0 默认)。multi_gpu: False 表明 worker 设计上单卡单进程,需要外层按 rank 分配,外层没做。

genesis(进程内后端)

  • 最糟:GenesisBackend.__init__unisim/backend/genesis/backend.py:78-94)不接受 device 入参,UniLab 侧 EnvCfg / genesis.yaml 也没有任何 device 字段。
  • gs.init(backend=gs.gpu) 会强制 torch.set_default_device("cuda:0")genesis/materialization.py:116 注释明确记录);backend 跟随 torch.cuda.current_device()genesis/backend.py:124-127),而 UniLab/uni_rl 全链路只有 off-policy learner 在 dp_sync.py:90torch.cuda.set_device,collector / PPO worker 无人 set。
  • resolve_backend_process_device 只对 mjwarp 返回非 None,genesis collector 无绑定;one-session-per-process 守卫意味着进程内无二次选择机会。

影响

任何 training.devices=[0,1,...] 的多卡训练,这三个后端的所有 rank env 物理仿真都挤在 devices[0] 一张卡上:该卡显存/算力成为瓶颈,其余卡只跑 learner;且用户无报错、无告警,表象是多卡 scaling 无效。

修复方向(供 maintainer 判断)

  1. isaacgym / isaacsim:构建 env 时把 rank device index 写进 env_cfg_override["isaacgym_device_id"/"isaacsim_device_id"]。注意 off-policy 路径 rank device 是 host-global index,PPO torchrun 路径是 LOCAL_RANK + 全量 CUDA_VISIBLE_DEVICES,两者 index 语义不同,需要各自换算。
  2. genesis:需要 unisim-core 侧为 GenesisBackend / init_genesis_session 新增 device 入参,并在 gs.init / current_device 之前 torch.cuda.set_device;UniLab 侧补 EnvCfg 字段与 rank device 透传。
  3. 过渡期防护:检测到 training.devices 多卡 + 这三个后端 + env device 全为 0 时输出 warning,避免静默挤卡。

仅为问题记录与方向建议,不在本 issue 内实施。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions