跳转至

env_manager.py — EnvManager 使用子进程模式管理仿真器的生命周期

文件路径: verl/experimental/vla/workers/env/env_manager.py 模块路径: verl.experimental.vla.workers.env.env_manager

文件概述

EnvManager 使用子进程模式管理仿真器的生命周期。它通过命令/结果队列与仿真器子进程通信,支持 NUMA 亲和性绑定和代理模式的方法调用。

核心设计

为什么用子进程?

机器人仿真器(如 MuJoCo、Isaac Sim)通常: 1. 有全局状态,不能在同一进程中运行多个实例 2. 可能不是线程安全的 3. 可能需要特定的 CPU 核心绑定(NUMA)

因此需要在独立子进程中运行。

架构

EnvManager (主进程)
    ├── command_queue  ──>  子进程 (仿真器)
    └── result_queue   <──

关键代码

启动仿真器

class EnvManager:
    def __init__(self, config, rank, world_size, env_cls):
        self.config = config
        self.env_cls = env_cls
        self.command_queue = mp.Queue()
        self.result_queue = mp.Queue()

    def start_simulator(self):
        """在子进程中启动仿真器"""
        self.process = mp.Process(
            target=self._simulator_worker,
            args=(self.command_queue, self.result_queue, self.config, self.env_cls)
        )
        self.process.start()

        # 可选:绑定到特定 NUMA 节点
        if self.config.get("numa_affinity"):
            self._set_numa_affinity(self.process.pid)

子进程主循环

@staticmethod
def _simulator_worker(command_queue, result_queue, config, env_cls):
    """仿真器子进程的主循环"""
    # 创建环境实例
    env = env_cls(config, ...)

    while True:
        # 等待命令
        command, args, kwargs = command_queue.get()

        if command == "shutdown":
            break

        # 执行命令并返回结果
        method = getattr(env, command)
        result = method(*args, **kwargs)
        result_queue.put(result)

代理模式调用

    def __getattr__(self, name):
        """代理模式:将方法调用转发给子进程

        使用方式:
            manager.chunk_step(actions)
            # 实际上通过队列发送给子进程执行
        """
        def proxy_method(*args, **kwargs):
            self.command_queue.put((name, args, kwargs))
            result = self.result_queue.get()
            return result
        return proxy_method

这种代理模式使得 EnvManager 可以像直接操作环境一样被使用:

# 这两种调用方式等效:
manager.chunk_step(actions)       # 通过代理
env.chunk_step(actions)           # 直接调用(如果在同一进程)

NUMA 亲和性

def _set_numa_affinity(self, pid):
    """将子进程绑定到特定的 NUMA 节点

    在多 CPU 服务器上,绑定仿真器到与 GPU
    同一 NUMA 节点的 CPU 核心可以减少内存延迟。
    """
    import os
    os.sched_setaffinity(pid, self.numa_cores)

核心类/函数列表

名称 类型 说明
EnvManager 类 子进程仿真器管理器
start_simulator 方法 启动仿真器子进程
_simulator_worker 静态方法 子进程主循环
__getattr__ 方法 代理模式方法转发
_set_numa_affinity 方法 NUMA 核心绑定

与其他模块的关系

  • 被 EnvWorker(env_worker.py)创建和使用
  • 管理 LiberoEnv 或 IsaacEnv 的子进程实例

小结

EnvManager 通过进程间通信(队列)隔离了仿真器的运行环境。代理模式让调用者不需要感知子进程的存在。NUMA 亲和性优化确保了在大规模服务器上的性能。