| |
| |
| """Tests for ScaledMM kernel selection logic (CPU-only) |
| |
| Run `pytest tests/kernels/quantization/test_scaled_mm_kernel_selection.py`. |
| """ |
|
|
| import inspect |
| from abc import ABC |
| from unittest.mock import patch |
|
|
| import pytest |
| import torch |
|
|
| from vllm.model_executor.kernels.linear import ( |
| AiterInt8ScaledMMLinearKernel, |
| CPUInt8ScaledMMLinearKernel, |
| Int8ScaledMMLinearKernel, |
| Int8ScaledMMLinearLayerConfig, |
| ScaledMMLinearKernel, |
| init_int8_linear_kernel, |
| register_linear_kernel, |
| ) |
| from vllm.platforms import PlatformEnum |
|
|
| pytestmark = pytest.mark.cpu_test |
|
|
|
|
| def test_is_supported_is_abstract(): |
| """Test that is_supported() is properly defined as abstract.""" |
| assert issubclass(ScaledMMLinearKernel, ABC) |
| assert hasattr(ScaledMMLinearKernel, "is_supported") |
|
|
|
|
| def test_cpu_kernel_implements_is_supported(): |
| """Test that CPUInt8ScaledMMLinearKernel implements is_supported() method.""" |
| assert hasattr(CPUInt8ScaledMMLinearKernel, "is_supported"), ( |
| "CPUInt8ScaledMMLinearKernel missing is_supported() method" |
| ) |
| |
| |
| assert inspect.ismethod( |
| CPUInt8ScaledMMLinearKernel.is_supported |
| ) or inspect.isfunction(CPUInt8ScaledMMLinearKernel.is_supported), ( |
| "CPUInt8ScaledMMLinearKernel.is_supported() should be a classmethod" |
| ) |
| |
| result, reason = CPUInt8ScaledMMLinearKernel.is_supported() |
| assert isinstance(result, bool), "is_supported() should return a bool" |
| assert reason is None or isinstance(reason, str), "reason should be str or None" |
|
|
|
|
| def test_aiter_kernel_implements_is_supported(): |
| """Test that AiterInt8ScaledMMLinearKernel implements is_supported() method.""" |
| assert hasattr(AiterInt8ScaledMMLinearKernel, "is_supported"), ( |
| "AiterInt8ScaledMMLinearKernel missing is_supported() method" |
| ) |
| |
| |
| assert inspect.ismethod( |
| AiterInt8ScaledMMLinearKernel.is_supported |
| ) or inspect.isfunction(AiterInt8ScaledMMLinearKernel.is_supported), ( |
| "AiterInt8ScaledMMLinearKernel.is_supported() should be a classmethod" |
| ) |
| |
| |
| result, reason = AiterInt8ScaledMMLinearKernel.is_supported() |
| assert isinstance(result, bool), "is_supported() should return a bool" |
| assert reason is None or isinstance(reason, str), "reason should be str or None" |
| |
| |
|
|
|
|
| def test_cpu_kernel_accepts_all_configs(): |
| """Test that CPUInt8ScaledMMLinearKernel accepts all config combinations.""" |
| configs = [ |
| Int8ScaledMMLinearLayerConfig( |
| is_channelwise=False, |
| is_static_input_scheme=True, |
| input_symmetric=True, |
| ), |
| Int8ScaledMMLinearLayerConfig( |
| is_channelwise=True, |
| is_static_input_scheme=False, |
| input_symmetric=False, |
| ), |
| ] |
|
|
| for config in configs: |
| can_impl, reason = CPUInt8ScaledMMLinearKernel.can_implement(config) |
| assert can_impl, ( |
| f"CPUInt8ScaledMMLinearKernel should accept config {config}: {reason}" |
| ) |
|
|
|
|
| class OOTInt8ScaledMMLinearKernel(Int8ScaledMMLinearKernel): |
| @classmethod |
| def is_supported( |
| cls, compute_capability: int | None = None |
| ) -> tuple[bool, str | None]: |
| return True, None |
|
|
| @classmethod |
| def can_implement(cls, c: Int8ScaledMMLinearLayerConfig) -> tuple[bool, str | None]: |
| return True, None |
|
|
| def process_weights_after_loading(self, layer: torch.nn.Module) -> None: |
| pass |
|
|
| def apply_weights( |
| self, |
| layer: torch.nn.Module, |
| x: torch.Tensor, |
| bias: torch.Tensor | None = None, |
| ) -> torch.Tensor: |
| pass |
|
|
|
|
| @patch("vllm.model_executor.kernels.linear.current_platform") |
| def test_register_oot_linear_kernel(platform_mock): |
| """Test that the linear kernel registration works correctly.""" |
| platform_mock._enum = PlatformEnum.OOT |
| register_linear_kernel(OOTInt8ScaledMMLinearKernel, PlatformEnum.OOT, "int8") |
|
|
| kernel = init_int8_linear_kernel(True, True, True, "module") |
|
|
| assert isinstance(kernel, OOTInt8ScaledMMLinearKernel), ( |
| "init_int8_linear_kernel should return an instance of the registered kernel" |
| ) |
|
|