Prhub

#39856 [XPU] update dp rank w/o env-var isolation

原始 PR 作者 zhenwei-intel 合并时间 2026-05-12 14:49 文件变更 2 提交数 8 评论 10 代码增减 +60 / -17

执行摘要

XPU DP 改用 rank 偏移分配设备,移除环境变量隔离

原有XPU DP依赖ZE_AFFINITY_MASK限制每个worker可见设备,但DP+EP时EP需要看到全部设备,导致设备号错乱。此PR改用与GPU worker一致的方式:在init_device中根据DP local rank和TP/PP world size调整local_rank,从而每个worker使用独立的xpu设备号。见PR body及评论。

建议XPU后端开发者与评审仔细阅读,此PR是重要的正确性修复。lazy init模式值得借鉴;未来可考虑将activities提取为父类方法以统一profile实现。

讨论亮点
  1. 正确性bug:gemini-code-assist[bot]指出local_rank在init_device中调整后profiler已在构造函数初始化,导致profiler设备不匹配。作者将profiler改为lazy init解决。
  2. 设计讨论:jikunshang建议复用父类profile方法,作者指出需提取activities列表,当前保留override,未来可提炼。
  3. 代码简化:jikunshang建议utils.py中条件写法更清晰,作者接受并更新。

实现拆解

  1. 在XPUWorker.init_device中,当满足条件(非ray/external_launcher后端且nnodes_within_dp==1)时,通过data_parallel_rank_local或data_parallel_index获取DP local rank,乘以tp_pp_world_size后累加到self.local_rank上,并添加边界断言。
  2. 将profiler初始化从__init__移至新增的profile方法中,采用lazy init模式:仅在profile(is_start=True)且self.profiler is None时创建TorchProfilerWrapper实例,最后调用父类profile。
  3. 在vllm/v1/engine/utils.py中,将DP设备环境隔离条件由not current_platform.is_cuda_alike()扩展为not (current_platform.is_cuda_alike() or current_platform.is_xpu()),即XPU与CUDA一样使用torch.accelerator.set_device_index而非环境变量隔离。
  4. 无自动化测试新增,但作者提供手动命令行验证。
文件 模块 状态 重要度
vllm/v1/worker/xpu_worker.py XPU 工作器 modified 7.31
vllm/v1/engine/utils.py 引擎工具 modified 5.58

关键符号

init_device profile

关键源码片段

vllm/v1/worker/xpu_worker.py core-logic

主要变更文件:实现 DP rank 调整、lazy profiler 初始化、profile 方法重写

# xpu_worker.py - init_device 中 DP rank 调整段
def init_device(self):
    # 在 DP 模式下,XPU workers 能看到所有可见设备。
    # 通过 DP local rank 偏移 local_rank 来分配不同设备。
    parallel_config = self.parallel_config
    if (
        parallel_config.distributed_executor_backend not in ("ray", "external_launcher")
        and parallel_config.data_parallel_backend != "ray"
        and parallel_config.nnodes_within_dp == 1
    ):
        dp_local_rank = parallel_config.data_parallel_rank_local
        if dp_local_rank is None:
            dp_local_rank = parallel_config.data_parallel_index
        tp_pp_world_size = (
            parallel_config.pipeline_parallel_size
            * parallel_config.tensor_parallel_size
        )
        # 核心:将 DP 偏移加到 local_rank 上
        self.local_rank += dp_local_rank * tp_pp_world_size
​
        visible_device_count = torch.accelerator.device_count()
        assert self.local_rank < visible_device_count, (
            f"DP adjusted local rank {self.local_rank} is out of bounds. "
        )
        # ... 后续设置设备
​
# xpu_worker.py - profile 方法(lazy init 模式)
def profile(self, is_start: bool = True, profile_prefix: str | None = None):
    # 确保 profiler 已配置,否则抛异常
    if self.profiler_config is None or self.profiler_config.profiler is None:
        raise RuntimeError(
            "Profiling is not enabled. Please set --profiler-config to enable "
            "profiling. ..."
        )
    # lazy 初始化:只有在第一次 start 时才创建 profiler
    if is_start and self.profiler is None:
        from vllm.distributed.utils import get_worker_rank_suffix
        rank_suffix = get_worker_rank_suffix(global_rank=self.rank)
        trace_name = (
            f"{profile_prefix}_{rank_suffix}" if profile_prefix else rank_suffix
        )
        self.profiler = TorchProfilerWrapper(
            self.profiler_config,
            worker_name=trace_name,
            local_rank=self.local_rank,
            activities=["CPU", "XPU"],
        )
    # 调用父类进行实际的 start / stop
    super().profile(is_start=is_start, profile_prefix=profile_prefix)

评论区精华

profiler 初始化时机 正确性

gemini-code-assist[bot] 指出 local_rank 在 init_device 中调整后,profiler 已在构造函数中初始化,会导致 profiler 使用错误的设备索引或 trace 文件冲突

结论:作者将 profiler 初始化从 __init__ 移除,改为在 profile 方法中 lazy init,解决不匹配问题 · 已解决

复用父类 profile 方法 设计

jikunshang 建议 XPUWorker 的 profile 方法可以复用父类 GPUWorker 的 profile,避免重复代码

结论:作者表示需将 activities 提取为父类方法才能复用,当前保留 override,未来可重构 · 待处理

utils.py 条件简化 style

jikunshang 建议将条件改为 needs_device_env_isolation = not (current_platform.is_cuda_alike() or current_platform.is_xpu()),更清晰

结论:作者接受建议并更新代码 · 已解决

风险与影响

  1. profiler lazy init:若profile方法不被调用,profiler不会被创建,但现有调用路径均通过外部触发,风险低。
  2. DP rank调整条件排除了ray/external_launcher后端及nnodes_within_dp != 1场景,这些场景仍使用旧环境变量隔离,可能引起不一致。
  3. 缺少单元测试覆盖新的rank计算逻辑,未来修改可能退化。
  4. 用户若依赖旧ZE_AFFINITY_MASK行为可能受影响,但新行为与GPU worker一致,更符合预期。

影响仅限XPU平台上使用DP(可能结合EP)的用户,修复了设备分配错误。不使用DP或仅CUDA用户无影响。团队维护成本降低,因新方式复用GPU worker设计。

缺少测试覆盖 profiler 延迟初始化风险 DP rank 假设条件敏感

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论