Files
1Cat-vLLM/tests/quantization/test_sm70_awq_kernel_selection.py
yangzhuxinyzx c9d825d5cf [Core] Consolidate prepared SM70 linear and native policy ownership
Bind linear implementations during preparation, partition native tuning and engine scratch ownership, and retain legacy imports and operator defaults. Extend shared configuration and execution explanations.

Assisted-by: OpenAI Codex
Signed-off-by: yangzhuxinyzx <153831768+yangzhuxinyzx@users.noreply.github.com>
2026-10-09 13:31:46 +08:00

143 lines
4.8 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
import json
import os
from dataclasses import replace
from pathlib import Path
from types import SimpleNamespace
import pytest
import torch
from tools.sm70_awq_route_snapshot import snapshot
from vllm import envs
from vllm.config.kernel import KernelConfig, Sm70AwqConfig
from vllm.model_executor.kernels import linear
from vllm.model_executor.kernels.linear import choose_mp_linear_kernel
from vllm.model_executor.kernels.linear.mixed_precision.sm70_awq import (
Sm70AwqLinearLayerConfig,
TurboMindAwqLinearKernel,
)
from vllm.platforms import PlatformEnum
from vllm.scalar_type import scalar_types
pytestmark = pytest.mark.cpu_test
@pytest.fixture(autouse=True)
def clean_route_environment(monkeypatch):
monkeypatch.setattr(
linear, "current_platform", SimpleNamespace(_enum=PlatformEnum.CUDA)
)
for name in list(os.environ):
if name.startswith("VLLM_"):
monkeypatch.delenv(name)
envs.disable_envs_cache()
yield
envs.disable_envs_cache()
def config():
policy = Sm70AwqConfig()
policy.resolve()
return Sm70AwqLinearLayerConfig(
full_weight_shape=(2560, 3584),
partition_weight_shape=(2560, 3584),
weight_type=scalar_types.uint4,
act_type=torch.float16,
group_size=32,
zero_points=True,
has_g_idx=False,
policy=policy,
)
def test_retained_category_snapshot():
golden = Path(__file__).parent / "data/sm70_awq_routes.json"
assert snapshot() == json.loads(golden.read_text())
def test_shared_selector_and_provider(monkeypatch):
monkeypatch.setattr(torch.ops, "_C", SimpleNamespace(awq_sm70_prepare=True))
assert choose_mp_linear_kernel(config(), 70) is TurboMindAwqLinearKernel
@pytest.mark.parametrize("group", [32, 64, 128])
def test_capability_independent_of_user_policy(monkeypatch, group):
monkeypatch.setattr(torch.ops, "_C", SimpleNamespace(awq_sm70_prepare=True))
cfg = replace(config(), group_size=group, policy=Sm70AwqConfig(enabled=False))
assert TurboMindAwqLinearKernel.can_implement(cfg) == (True, None)
def test_capability_failure_reasons(monkeypatch):
monkeypatch.setattr(torch.ops, "_C", SimpleNamespace())
supported, reason = TurboMindAwqLinearKernel.can_implement(config())
assert not supported and "native" in reason
supported, reason = TurboMindAwqLinearKernel.can_implement(
replace(config(), group_size=16)
)
assert not supported and "group_size" in reason
supported, reason = TurboMindAwqLinearKernel.can_implement(
replace(config(), zero_points=False)
)
assert not supported and "asymmetric" in reason
supported, reason = TurboMindAwqLinearKernel.can_implement(
replace(config(), act_type=torch.bfloat16)
)
assert not supported and "float16" in reason
def test_disable_uses_common_selector(monkeypatch):
monkeypatch.setattr(torch.ops, "_C", SimpleNamespace(awq_sm70_prepare=True))
monkeypatch.setenv("VLLM_DISABLED_KERNELS", "TurboMindAwqLinearKernel")
envs.disable_envs_cache()
with pytest.raises(ValueError, match="disabled"):
choose_mp_linear_kernel(config(), 70)
def test_alias_precedence_and_no_environment_mutation(monkeypatch):
monkeypatch.setenv("VLLM_SM70_AWQ_TURBOMIND", "0")
monkeypatch.setenv("VLLM_SM70_AWQ_PREFILL_EXACT_DENSE", "0")
monkeypatch.setenv("VLLM_SM70_AWQ_MLP_ENGINE", "1")
before = dict(os.environ)
legacy = Sm70AwqConfig()
legacy.resolve()
assert not legacy.enabled and not legacy.prefill_exact_dense and legacy.fused_silu
explicit = Sm70AwqConfig(enabled=True, fused_silu=False)
explicit.resolve()
assert explicit.enabled and not explicit.fused_silu
assert dict(os.environ) == before
def test_two_engines_have_isolated_policy_and_hash(monkeypatch):
first = KernelConfig()
first.sm70_awq.resolve()
monkeypatch.setenv("VLLM_SM70_AWQ_TURBOMIND", "0")
envs.disable_envs_cache()
second = KernelConfig()
second.sm70_awq.resolve()
first.sm70_awq.resolve()
assert first.sm70_awq.enabled and not second.sm70_awq.enabled
assert first.compute_hash() != second.compute_hash()
def test_unused_awq_policy_does_not_perturb_an_nvfp4_graph():
cfg = KernelConfig()
cfg.sm70_nvfp4.resolve(qualified=True)
before = cfg.compute_hash()
cfg.sm70_awq.enabled = False
cfg.sm70_awq.prefill_exact_dense = False
cfg.sm70_awq.native.awq_dense_tune_max_m = 5
assert cfg.compute_hash() == before
@pytest.mark.parametrize(
"backend,enabled", [("auto", True), ("turbomind", True), ("marlin", False)]
)
def test_shared_legacy_backend_precedence(monkeypatch, backend, enabled):
monkeypatch.setenv("VLLM_SM70_QUANT_BACKEND", backend)
cfg = Sm70AwqConfig()
cfg.resolve()
assert cfg.enabled == enabled