Prhub

#56106 [ROCm][CI] Fix moe layer tests for fp8 dtype compatibility

原始 PR 作者 divakar-amd 合并时间 2026-09-10 01:48 文件变更 2 提交数 2 评论 2 代码增减 +11 / -8

执行摘要

修复 MoE 层测试中 FP8 数据类型在 ROCm 平台不兼容的问题。

PR body 明确指出:'Fixes MoE layer tests to support ROCm's float8_e4m3fnuz dtype alongside CUDA/XPU's float8_e4m3fn'。问题根源在于测试代码中直接使用了 CUDA 特有的 torch.float8_e4m3fn 类型进行断言和操作,导致在 ROCm 平台上测试失败,因为 ROCm 使用 float8_e4m3fnuz 类型。需要一种平台自适应的方式来获取和检查 FP8 数据类型。

这是一个小而重要的平台兼容性修复。虽然变更范围小,但它解决了一个导致 CI 在特定平台失败的实际问题,并采用了推荐的最佳实践(使用平台抽象而非硬编码)。对于负责维护测试、关注多平台支持或处理 ROCm 相关问题的工程师,值得精读。其核心决策——使用 current_platform.fp8_dtype() 和 is_fp8() 替代硬编码——是一个值得在其他测试代码中推广的模式。

讨论亮点

本次 PR 的 review 讨论较少。由维护者 AndreasKaratzas 触发了 CI 并批准了合并。claude[bot] 的评论仅为自动化流程提示,未涉及技术讨论。没有发现关于设计、风险或实现的争议。

实现拆解

本次变更集中在两个测试辅助文件,旨在使测试代码与具体平台解耦。

  1. 核心变更:在 tests/kernels/moe/test_moe_layer.py 中,将硬编码的全局变量 fp8_dtype = torch.float8_e4m3fn 改为动态获取 fp8_dtype = current_platform.fp8_dtype()。这确保了在不同平台(CUDA、ROCm、XPU)上测试都能使用正确的本机 FP8 数据类型。
  2. 通用化类型检查:在 tests/kernels/moe/utils.py 的 moe_quantize_weights_2d 函数中,移除了对 quant_dtype == torch.float8_e4m3fn 的硬编码断言和分支判断。取而代之的是导入并使用通用的 is_fp8() 工具函数,通过 is_fp8_dtype = is_fp8(quant_dtype) 来检测任意平台的 FP8 类型(如 CUDA 的 float8_e4m3fn 和 ROCm 的 float8_e4m3fnuz),从而统一了断言和后续的 per_block_cast_to_fp8 与 scaled_fp8_quant 调用路径。
  3. Mock 覆盖增强:在 tests/kernels/moe/test_moe_layer.py 的 override_normalize_e4m3fn_to_e4m3fnuz 函数中,增加了对 vllm.model_executor.layers.quantization.fp8.normalize_e4m3fn_to_e4m3fnuz 模块级别的 mock 覆盖。这是因为 normalize_e4m3fn_to_e4m3fnuz 函数可能在不同的量化模块中被引用,此改动确保无论从哪个路径调用,mock 都能生效,从而在不需要实际进行类型转换的测试中隔离平台特定行为。
文件 模块 状态 重要度
tests/kernels/moe/test_moe_layer.py MoE 层测试 modified 4.46
tests/kernels/moe/utils.py 测试工具 modified 4.75

关键符号

moe_quantize_weights_2d override_normalize_e4m3fn_to_e4m3fnuz

关键源码片段

tests/kernels/moe/test_moe_layer.py test-coverage

主测试文件,将硬编码的 FP8 数据类型替换为平台动态类型,并增强了 mock 覆盖以处理不同导入路径。

# 变更前:硬编码为 CUDA 特有的 FP8 类型,导致在 ROCm 等平台测试失败。
fp8_dtype = torch.float8_e4m3fn # current_platform.fp8_dtype
​
# 变更后:动态获取当前平台原生的 FP8 数据类型,实现了跨平台兼容。
fp8_dtype = current_platform.fp8_dtype()
​
...
​
# 变更前:mock 只覆盖了一个可能的导入路径。
def override_normalize_e4m3fn_to_e4m3fnuz():
    vllm.model_executor.layers.quantization.utils.w8a8_utils.normalize_e4m3fn_to_e4m3fnuz = mock_normalize_e4m3fn_to_e4m3fnuz # noqa: E501
​
# 变更后:mock 覆盖了另一个可能的导入路径,确保测试环境中的类型转换被完全旁路。
def override_normalize_e4m3fn_to_e4m3fnuz():
    vllm.model_executor.layers.quantization.utils.w8a8_utils.normalize_e4m3fn_to_e4m3fnuz = mock_normalize_e4m3fn_to_e4m3fnuz # noqa: E501
    vllm.model_executor.layers.quantization.fp8.normalize_e4m3fn_to_e4m3fnuz = (
        mock_normalize_e4m3fn_to_e4m3fnuz # noqa: E501
    )
tests/kernels/moe/utils.py test-coverage

测试工具函数,将 `moe_quantize_weights_2d` 中的 FP8 数据类型检查从硬编码比较改为使用通用的 `is_fp8()` 函数。

# 变更前:使用硬编码的 `torch.float8_e4m3fn` 进行类型断言和分支判断。
assert (
    quant_dtype == torch.float8_e4m3fn
    or quant_dtype == torch.int8
    or quant_dtype == "nvfp4"
), "only fp8/int8/nvfp4 supported"
...
elif quant_dtype == torch.float8_e4m3fn:
    w, w_s = per_block_cast_to_fp8(w, block_shape)
...
elif quant_dtype == torch.float8_e4m3fn:
    w, w_s = ops.scaled_fp8_quant(
        w, w_s, use_per_token_if_dynamic=per_token_quant
    )
​
# 变更后:导入并使用通用的 `is_fp8()` 工具函数,它能识别所有平台的 FP8 类型。
from vllm.model_executor.layers.quantization.utils.fp8_utils import is_fp8
...
​
def moe_quantize_weights_2d(...):
    is_fp8_dtype = is_fp8(quant_dtype) # 使用工具函数检测 FP8 类型
    assert is_fp8_dtype or quant_dtype == torch.int8 or quant_dtype == "nvfp4", (
        "only fp8/int8/nvfp4 supported"
    )
    ...
    elif is_fp8_dtype: # 使用统一的检测结果进行分支
        w, w_s = per_block_cast_to_fp8(w, block_shape)
    ...
    elif is_fp8_dtype: # 使用统一的检测结果进行分支
        w, w_s = ops.scaled_fp8_quant(
            w, w_s, use_per_token_if_dynamic=per_token_quant
        )

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  1. 测试回归风险:本次变更仅限于测试文件 (tests/kernels/moe/utils.py 和 tests/kernels/moe/test_moe_layer.py),不涉及核心源码或推理逻辑,因此对生产环境的回归风险极低。
  2. 平台兼容性风险:引入 current_platform.fp8_dtype() 和 is_fp8() 是为了提升跨平台兼容性,风险在于这些工具函数本身是否对所有目标平台(CUDA、ROCm、XPU)正确实现了类型获取和判断。从现有代码库上下文看,current_platform 和 is_fp8 是成熟的抽象,风险可控。
  3. Mock 覆盖遗漏风险:override_normalize_e4m3fn_to_e4m3fnuz 新增的 mock 路径覆盖是预防性修复,若存在其他未覆盖的导入路径,可能导致在某些环境下测试仍会尝试执行实际的类型转换,但鉴于此修改明确且范围集中,风险较低。
  1. 对用户的影响:无直接影响。这是测试基础设施的改进,不改变 vLLM 的功能或 API。
  2. 对系统的影响:提升了 MoE 内核测试套件的跨平台稳定性和 CI 可靠性,特别是在 ROCm 平台上。这有助于确保 MoE 相关功能在所有受支持硬件上的正确性,间接提升了系统的整体质量。
  3. 对团队的影响:为平台兼容性测试树立了良好范例,展示了如何通过抽象平台特定类型(如 FP8 dtype)和通用化检查函数来编写可移植的测试代码。这可以指导未来类似问题的解决。
测试平台兼容性

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论