执行摘要
- 一句话:修复 Ascend A5 硬件因 HDK 版本问题无法开启 IPC 的 bug
- 推荐动作:本 PR 是一个重要的、针对性强的 bugfix。它解决了特定硬件上的功能阻断问题,且实现清晰,测试覆盖全面。推荐精读,关注点在于:
1) AscendHardwareVersion 枚举的设计及其作为未来硬件适配扩展点的潜力;
2) get_npu_versions 返回值签名变更的影响范围确认;
3) 测试中通过 @patch.dict(sys.modules, {...}) 模拟 torch_npu 模块的方法。
功能与动机
在 Ascend A5 硬件上,由于 HDK(Hypervisor Development Kit)版本问题,使用原有的 IPC 版本检查逻辑(依赖 software_version 和 cann_version)会错误地判定 IPC 不受支持。PR body 中明确指出:“Fix the issue of A5 being unable to open IPC due to the HDK version problem.” 这是一个针对特定硬件的兼容性修复,旨在恢复 A5 硬件的 IPC 功能。
实现拆解
- 定义硬件版本枚举:在
verl/utils/device.py 中新增 AscendHardwareVersion 枚举类(IntEnum),用于表示 NPU 芯片代次,包含 NONE、A2、A3、A5 和 MAX_VERSION 等成员。
- 增强
get_npu_versions 函数:修改 verl/utils/device.py 中的 get_npu_versions 函数。
- 在函数开头尝试导入
torch_npu 并调用 torch_npu.npu.get_device_name() 来获取硬件名称。
- 根据设备名称字符串(如 'Ascend910_95', 'Ascend950', 'Ascend910_93', 'Ascend910B', 'A2G')推断并返回对应的
AscendHardwareVersion 枚举值。
- 函数返回值从
(software_version, carn_version) 变更为 (hardware_version, software_version, carn_version)。
- 调整 IPC 支持检测逻辑:在
verl/plugin/platform/platform_npu.py 的 PlatformNPU.is_ipc_supported 方法中。
- 更新导入语句以包含
AscendHardwareVersion。
- 解包
get_npu_versions 返回的三元组为 hardware_version, software_version, carn_version。
- 新增短路逻辑:如果
hardware_version == AscendHardwareVersion.A5,则直接返回 True,不再调用 check_ipc_version_support。
- 配套测试:修改
tests/utils/test_check_ipc_version_support_on_npu.py。
- 新增辅助函数
_fake_torch_npu 用于模拟不同硬件名称。
- 新增
TestGetNPUVersions 类下的多个测试用例(如 test_hardware_version_a5_910_95, test_hardware_version_a3 等)验证 get_npu_versions 对不同设备名称的正确分类。
- 新增
TestIsIPCSupported 类,专门测试 PlatformNPU.is_ipc_supported 方法,包括 A5 短路返回 True 和非 A5 委托给版本检查两种场景。
- 调整了现有测试用例(如
test_get_npu_versions_success)以适应新的三元组返回值。
关键文件:
verl/utils/device.py(模块 设备工具;类别 source;类型 dependency-wiring;符号 AscendHardwareVersion, get_npu_versions): 核心变更文件,新增硬件版本枚举并重构 get_npu_versions 函数以返回硬件型号。
verl/plugin/platform/platform_npu.py(模块 平台插件;类别 source;类型 dependency-wiring): 使用 get_npu_versions 的调用方,实现了针对 A5 硬件的 IPC 支持短路逻辑。
tests/utils/test_check_ipc_version_support_on_npu.py(模块 IPC 版本检查测试;类别 test;类型 test-coverage;符号 _fake_torch_npu, test_hardware_version_a5_910_95, test_hardware_version_a5_950, test_hardware_version_a3): 配套测试文件,全面覆盖了新增的硬件版本检测逻辑和 IPC 支持判断逻辑。
关键符号:get_npu_versions, PlatformNPU.is_ipc_supported, _fake_torch_npu
关键源码片段
verl/utils/device.py
核心变更文件,新增硬件版本枚举并重构 get_npu_versions 函数以返回硬件型号。
# 在 verl/utils/device.py 中新增的硬件版本枚举和检测逻辑
from enum import IntEnum, unique
@unique
class AscendHardwareVersion(IntEnum):
"""Ascend NPU 芯片代次枚举。"""
NONE = 0 # torch_npu 不可用或无法识别
A2 = 2 # Ascend910B, A2G
A3 = 3 # Ascend910_93
A5 = 5 # Ascend910_95, Ascend950
MAX_VERSION = 999 # 未知或更新型号
def get_npu_versions() -> tuple[AscendHardwareVersion, str, str]:
"""获取 NPU 芯片代次、软件版本和 CANN 工具包版本。
Returns:
tuple[AscendHardwareVersion, str, str]: 三元组 (hardware_version, software_version, cann_version)
"""
# 尝试通过 torch_npu 获取设备名称以判断硬件型号
try:
import torch_npu
device_name = torch_npu.npu.get_device_name()
except Exception:
hardware_version = AscendHardwareVersion.NONE
else:
if "Ascend910_95" in device_name or "Ascend950" in device_name:
hardware_version = AscendHardwareVersion.A5
elif "Ascend910_93" in device_name:
hardware_version = AscendHardwareVersion.A3
elif "Ascend910B" in device_name or "A2G" in device_name:
hardware_version = AscendHardwareVersion.A2
else:
hardware_version = AscendHardwareVersion.MAX_VERSION
# ... 后续的 software_version 和 cann_version 获取逻辑保持不变 ...
return hardware_version, software_version, cann_version
verl/plugin/platform/platform_npu.py
使用 get_npu_versions 的调用方,实现了针对 A5 硬件的 IPC 支持短路逻辑。
# 在 verl/plugin/platform/platform_npu.py 的 is_ipc_supported 方法中的关键逻辑
def is_ipc_supported(self) -> bool:
import subprocess
from verl.utils.device import AscendHardwareVersion, check_ipc_version_support, get_npu_versions
try:
# 解包新的三元组返回值
hardware_version, software_version, carn_version = get_npu_versions()
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Failed to execute npu-smi command: {e}") from e
except Exception as e:
raise RuntimeError(f"Error checking IPC support: {e}") from e
# 针对 A5 硬件的短路逻辑:直接支持 IPC
if hardware_version == AscendHardwareVersion.A5:
return True
# 非 A5 硬件回退到原有的版本检查逻辑
return check_ipc_version_support(software_version, carn_version)
tests/utils/test_check_ipc_version_support_on_npu.py
配套测试文件,全面覆盖了新增的硬件版本检测逻辑和 IPC 支持判断逻辑。
# 在 tests/utils/test_check_ipc_version_support_on_npu.py 中,用于模拟不同硬件名称的辅助函数
import sys
from unittest.mock import MagicMock
def _fake_torch_npu(device_name):
"""构建一个模拟的 torch_npu 模块,其 npu.get_device_name 返回指定名称。"""
fake = MagicMock()
fake.npu.get_device_name.return_value = device_name
return fake
# 示例测试用例,验证 A5 硬件(Ascend910_95)被正确识别
@patch.dict(sys.modules, {"torch_npu": _fake_torch_npu("Ascend910_95")})
@patch("subprocess.run")
@patch("platform.machine")
@patch("os.path.exists")
@patch("builtins.open", new_callable=mock_open, read_data="version=8.3.rc1\n")
def test_hardware_version_a5_910_95(self, mock_file, mock_exists, mock_machine, mock_run):
mock_run.return_value = Mock(stdout="Software Version : 25.5.0\n", check=True)
mock_machine.return_value = "x86_64"
mock_exists.return_value = True
hardware_version, _, _ = get_npu_versions()
self.assertEqual(hardware_version, AscendHardwareVersion.A5)
# 测试 A5 硬件在 is_ipc_supported 中的短路返回 True 行为
@patch("verl.utils.device.check_ipc_version_support")
@patch("verl.utils.device.get_npu_versions")
def test_a5_short_circuit_returns_true(self, mock_get_versions, mock_check):
mock_get_versions.return_value = (AscendHardwareVersion.A5, "24.0.0", "7.0.0")
from verl.plugin.platform.platform_npu import PlatformNPU
platform = PlatformNPU()
self.assertTrue(platform.is_ipc_supported())
# 断言 check_ipc_version_support 未被调用,证实短路逻辑生效
mock_check.assert_not_called()
评论区精华
本 PR 没有公开的 review 讨论评论。根据提交记录,共两个提交:‘ipc_fix patch’ 和 ‘pre-commit fix’。审核者 wucong25 最终状态为 ‘APPROVED’。
风险与影响
关联脉络
- PR #7604 [megatron, ci] chore: upgrade Ascend stack to Megatron 0.18.0: 同属 Ascend NPU 硬件适配和工具链升级范畴。本 PR 解决了 A5 硬件的 IPC 问题,而 PR#7604 则是升级了整个 Ascend 软件栈(包括 Megatron),两者共同推进了 Ascend 平台的稳定性和功能性。
- PR #7779 [vllm, hardware] fix: patch vllm-ascend for GLM-5.2 RL training on Ascend NPUs: 同为 Ascend NPU 硬件兼容性修复。PR#7779 解决了 vLLM 在 Ascend NPU 上训练 GLM-5.2 模型的兼容性问题,本 PR 则解决了 A5 硬件本身的 IPC 检测问题。两者都是硬件特定的 bugfix,体现了项目对 Ascend 生态的持续投入。
- PR #7722 [perf, tool] fix: Avoid overlapping rollout and training profilers in Trainer V1: 同属 rollout 模块的改进。本 PR 修复了影响 rollout 功能(IPC)的硬件兼容性问题,而 PR#7722 则修复了 rollout 与训练 profiler 的冲突。两者共同提升了 rollout 组件的稳定性和准确性。
参与讨论