Prhub

#52265 [UT][XPU] fix b12x UT

原始 PR 作者 mayuyuace 合并时间 2026-08-14 21:49 文件变更 2 提交数 5 评论 16 代码增减 +24 / -3

执行摘要

补注册 flashinfer_mxfp4 懒包装,b12x 测试改平台无关

Intel CI(buildkite intel-ci/builds/8908)中 test_b12x_mxfp8_linear.py 失败:b12x.py 执行 from vllm.utils.flashinfer import flashinfer_mxfp4_quantize,但该函数从未注册,monkeypatch.setattr 因没有可 patch 的对象而抛 AttributeError。PR body 明确给出根因(Root cause),并说明修复方式是与 flashinfer_fp4_quantize 等既有懒加载包装保持一致。

值得快速浏览的小型修复 PR,不需要精读。两个可学习的点:一是 vllm 对 flashinfer 的懒加载包装约定(每个入口函数都要在 vllm/utils/flashinfer.py 手动登记,否则上游 import 与 monkeypatch 都会失败);二是 _mock_b12x_cuda_fp8_platform 用 SimpleNamespace 完整 mock 平台对象的写法,是让依赖特定平台的测试在任意 CI 设备上运行的通用模式。

讨论亮点

review 核心交锋如下:

  • stefankoncarevic 指出 fixture 替换了整个 current_platform 对象,但只暴露了模块用到的 5 个方法中的 2 个(is_fp8_fnuz、is_rocm),若未来 process_fp8_weight_block_strategy 调用 fp8_dtype(),会以 AttributeError 而非合理行为暴露;
  • AndreasKaratzas 认为 CI 反正要重跑,建议顺手补完;mayuyuace 确认 CI 失败与本 PR 无关后提交 6a7b57b 补齐全部方法,stefankoncarevic 回复 All good, thanks;
  • mgoin 在合并前向受影响社区致歉:Very sorry for the disruption folks!

实现拆解

  1. 根因修复:在 vllm/utils/flashinfer.py 的懒加载区段新增 flashinfer_mxfp4_quantize = _lazy_import_wrapper("flashinfer", "mxfp4_quantize"),与 fp4_quantize 等其它入口完全同构,保证 flashinfer 未安装时模块仍可正常导入。
  2. 平台无关化:tests/model_executor/kernels/test_b12x_mxfp8_linear.py 的 test_b12x_backend_does_not_intercept_unquantized_bf16 将硬编码的 .cuda() 与 device="cuda" 替换为 current_platform.device_type,使同一测试在 XPU 等设备上按当前平台构建张量与层。
  3. 新增 mock fixture:_mock_b12x_cuda_fp8_platform 通过 types.SimpleNamespace 整体替换 fp8_utils.current_platform,覆盖 is_fp8_fnuz、is_rocm、fp8_dtype、is_xpu、is_cuda_alike 五个方法,并分别应用于 test_b12x_block_fp8_process_weights_keeps_native_block_layout 与 test_b12x_block_fp8_upcasts_e8m0_weight_scales。
  4. review 加固:根据 stefankoncarevic 的提醒补齐最初遗漏的 fp8_dtype、is_xpu、is_cuda_alike(commit 6a7b57b)。

配套说明:无 schema、配置或部署改动;CI 通过 /ci run 触发验证,期间出现的 Buildkite 失败经确认与本 PR 无关。

文件 模块 状态 重要度
vllm/utils/flashinfer.py 工具层 modified 5.15
tests/model_executor/kernels/test_b12x_mxfp8_linear.py 量化测试 modified 5.59

关键符号

flashinfer_mxfp4_quantize _mock_b12x_cuda_fp8_platform test_b12x_backend_does_not_intercept_unquantized_bf16 test_b12x_block_fp8_process_weights_keeps_native_block_layout test_b12x_block_fp8_upcasts_e8m0_weight_scales

关键源码片段

vllm/utils/flashinfer.py core-logic

修复根因所在:为 b12x.py 依赖的 flashinfer_mxfp4_quantize 补充懒加载注册,否则任何 import 与 monkeypatch 都会失败。

# 所有 flashinfer 入口统一通过 _lazy_import_wrapper 延迟解析:
# 未安装 flashinfer 时模块仍可正常导入,运行期调用则走 fallback 逻辑。
flashinfer_fp4_quantize = _lazy_import_wrapper("flashinfer", "fp4_quantize")# 本次修复:b12x.py 直接 import 该符号并对其 monkeypatch,
# 但它此前从未注册,导致测试中的 setattr 抛出 AttributeError。
# 补上注册后,行为与 fp4_quantize 等其它懒包装完全一致。
flashinfer_mxfp4_quantize = _lazy_import_wrapper("flashinfer", "mxfp4_quantize")nvfp4_batched_quantize = _lazy_import_wrapper("flashinfer", "nvfp4_batched_quantize")
silu_and_mul_scaled_nvfp4_experts_quantize = _lazy_import_wrapper(
    "flashinfer", "silu_and_mul_scaled_nvfp4_experts_quantize"
)
tests/model_executor/kernels/test_b12x_mxfp8_linear.py test-coverage

测试主体:将硬编码 CUDA 设备改为 current_platform,并新增完整 mock 平台的 fixture,使 b12x 相关 UT 在 XPU 等设备上稳定运行。

@pytest.fixture
def _mock_b12x_cuda_fp8_platform(monkeypatch: pytest.MonkeyPatch) -> None:
    # b12x 权重处理只针对 CUDA 形态平台,但测试需要跑在任意 CI 设备上。
    # 通过 SimpleNamespace 整体替换 fp8_utils.current_platform,
    # 并一次性覆盖该模块会用到的全部方法,避免遗漏时出现 AttributeError。
    import vllm.model_executor.layers.quantization.utils.fp8_utils as fp8_utils
​
    monkeypatch.setattr(
        fp8_utils,
        "current_platform",
        types.SimpleNamespace(
            is_fp8_fnuz=lambda: False,
            is_rocm=lambda: False,
            fp8_dtype=lambda: torch.float8_e4m3fn,
            is_xpu=lambda: False,
            is_cuda_alike=lambda: True,
        ),
    )
​
​
# 两个权重处理测试复用该 fixture,在非 CUDA 平台上以 CUDA 语义执行
@pytest.mark.usefixtures("_mock_b12x_cuda_fp8_platform")
def test_b12x_block_fp8_process_weights_keeps_native_block_layout() -> None:
    ...
​
​
@pytest.mark.parametrize("scale_dtype", [torch.float8_e8m0fnu, torch.uint8])
@pytest.mark.usefixtures("_mock_b12x_cuda_fp8_platform")
def test_b12x_block_fp8_upcasts_e8m0_weight_scales(scale_dtype) -> None:
    ...

评论区精华

fixture 对 current_platform 的 mock 不完整 测试

stefankoncarevic 指出 _mock_b12x_cuda_fp8_platform 用 SimpleNamespace 替换了 fp8_utils 内整个 current_platform,但只包含 is_fp8_fnuz 与 is_rocm,缺 fp8_dtype、is_xpu、is_cuda_alike;未来模块内调用缺失方法会直接 AttributeError。AndreasKaratzas 建议在重跑 CI 前顺手补完。

结论:mayuyuace 在 commit 6a7b57b 补齐五个方法,stefankoncarevic 确认 'All good, thanks'。 · 已解决

CI 失败是否与本 PR 相关 question

AndreasKaratzas 提到 CI 不过,希望顺手处理;mayuyuace 给出 Buildkite 链接说明失败出现在与本 PR 无关的位置,建议更新分支后重试 CI。

结论:确认失败与本 PR 无关,随后在合入时保持干净基线。 · 已解决

风险与影响

  1. flashinfer.py 新增的懒加载包装在模块导入期不触发真实 flashinfer 加载(impl 为 None 时走 fallback),不存在因依赖缺失导致的导入崩溃;但若已安装的 flashinfer 版本缺少 mxfp4_quantize 属性,getattr 会返回 None,调用方需要自行处理。
  2. 测试中把硬编码 cuda 换成 current_platform.device_type:CUDA 机器上行为不变;在 XPU 上 ReplicatedLinear 会真实尝试在当前设备建层,若 XPU 侧算子缺失,测试可能暴露新的失败——这正是本次修复想验证的内容。
  3. fixture 属于侵入式整体替换 fp8_utils.current_platform:已覆盖五个方法,但未来 fp8_utils 若新增平台方法调用,需要同步维护该 namespace,否则会以 AttributeError 形式暴露。

用户侧无感知:生产推理路径不读取 flashinfer_mxfp4_quantize(仅补注册符号),推理行为不变。系统侧:Intel CI 恢复绿色,b12x 相关 UT 从仅在 CUDA 可跑变为跨平台可跑,为 XPU、ROCm 等设备复用同一套测试铺路。团队侧:形成可复制的平台 mock 样板(_mock_b12x_cuda_fp8_platform),后续类似依赖 CUDA 平台的测试可直接复用;同时强化 flashinfer 懒加载符号的登记纪律,每次新增 flashinfer API 都需在 vllm/utils/flashinfer.py 同步注册。

单行源码修复 测试 mock 平台对象 跨平台可移植性 mock 完整性需随模块演化维护

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论