213 lines
5.3 KiB
Python
213 lines
5.3 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
|
|
|
|
import pytest
|
|
import torch
|
|
|
|
from tests.kernels.allclose_default import get_default_atol, get_default_rtol
|
|
from tests.kernels.utils import opcheck
|
|
from vllm.platforms import CpuArchEnum, current_platform
|
|
from vllm.utils.torch_utils import set_random_seed
|
|
|
|
if not current_platform.is_cpu():
|
|
pytest.skip("skipping CPU-only tests", allow_module_level=True)
|
|
|
|
from vllm.model_executor.layers.activation import (
|
|
GELU,
|
|
FastGELU,
|
|
GeluAndMul,
|
|
NewGELU,
|
|
QuickGELU,
|
|
SiluAndMul,
|
|
)
|
|
|
|
DTYPES = [torch.bfloat16, torch.float32]
|
|
NUM_TOKENS = [7, 83]
|
|
D = [512, 2048]
|
|
SEEDS = [0]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("activation_cls", "fn"),
|
|
[
|
|
(SiluAndMul, torch.ops._C.silu_and_mul),
|
|
(GeluAndMul, torch.ops._C.gelu_and_mul),
|
|
(GeluAndMul, torch.ops._C.gelu_tanh_and_mul),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize("num_tokens", NUM_TOKENS)
|
|
@pytest.mark.parametrize("d", D)
|
|
@pytest.mark.parametrize("dtype", DTYPES)
|
|
@pytest.mark.parametrize("seed", SEEDS)
|
|
@torch.inference_mode()
|
|
def test_cpu_act_and_mul(
|
|
default_vllm_config,
|
|
activation_cls: type[torch.nn.Module],
|
|
fn: object,
|
|
num_tokens: int,
|
|
d: int,
|
|
dtype: torch.dtype,
|
|
seed: int,
|
|
) -> None:
|
|
set_random_seed(seed)
|
|
x = torch.randn(num_tokens, 2 * d, dtype=dtype)
|
|
|
|
layer = activation_cls()
|
|
out = layer(x)
|
|
ref_out = layer.forward_native(x)
|
|
|
|
torch.testing.assert_close(
|
|
out, ref_out, atol=get_default_atol(out), rtol=get_default_rtol(out)
|
|
)
|
|
|
|
output_shape = x.shape[:-1] + (x.shape[-1] // 2,)
|
|
raw_out = torch.empty(output_shape, dtype=x.dtype, device=x.device)
|
|
opcheck(fn, (raw_out, x))
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("activation_cls", "fn", "op_args"),
|
|
[
|
|
(NewGELU, torch.ops._C.gelu_new, ()),
|
|
(FastGELU, torch.ops._C.gelu_fast, ()),
|
|
(QuickGELU, torch.ops._C.gelu_quick, ()),
|
|
pytest.param(
|
|
GELU,
|
|
getattr(torch.ops._C, "activation_lut_bf16", None),
|
|
("gelu",),
|
|
marks=pytest.mark.skipif(
|
|
current_platform.get_cpu_architecture() != CpuArchEnum.ARM,
|
|
reason="activation_lut_bf16 is only built on Arm CPU",
|
|
),
|
|
),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize("num_tokens", NUM_TOKENS)
|
|
@pytest.mark.parametrize("d", D)
|
|
@pytest.mark.parametrize("dtype", DTYPES)
|
|
@pytest.mark.parametrize("seed", SEEDS)
|
|
@torch.inference_mode()
|
|
def test_cpu_unary_activation(
|
|
default_vllm_config,
|
|
activation_cls: type[torch.nn.Module],
|
|
fn: object,
|
|
op_args: tuple[str, ...],
|
|
num_tokens: int,
|
|
d: int,
|
|
dtype: torch.dtype,
|
|
seed: int,
|
|
) -> None:
|
|
set_random_seed(seed)
|
|
x = torch.randn(num_tokens, d, dtype=dtype)
|
|
layer = activation_cls()
|
|
out = layer(x)
|
|
ref_out = layer.forward_native(x)
|
|
torch.testing.assert_close(
|
|
out, ref_out, atol=get_default_atol(out), rtol=get_default_rtol(out)
|
|
)
|
|
# gelu with activation_lut_bf16 only makes sense for BF16
|
|
if not (activation_cls is GELU and dtype != torch.bfloat16):
|
|
raw_out = torch.empty_like(x)
|
|
opcheck(fn, (raw_out, x, *op_args))
|
|
|
|
|
|
@pytest.mark.parametrize("dtype", DTYPES)
|
|
@torch.inference_mode()
|
|
def test_cpu_gelu_tanh_and_mul(
|
|
default_vllm_config,
|
|
dtype: torch.dtype,
|
|
) -> None:
|
|
gate = torch.tensor(
|
|
[
|
|
[
|
|
-12.0,
|
|
-10.0,
|
|
-9.01,
|
|
-5.0,
|
|
-2.0,
|
|
-1.0,
|
|
-0.0,
|
|
0.0,
|
|
0.5,
|
|
1.0,
|
|
2.0,
|
|
5.0,
|
|
9.01,
|
|
10.0,
|
|
12.0,
|
|
11.0,
|
|
],
|
|
[
|
|
-7.5,
|
|
-4.5,
|
|
-3.0,
|
|
-1.5,
|
|
-0.75,
|
|
-0.25,
|
|
0.25,
|
|
0.75,
|
|
1.5,
|
|
3.0,
|
|
4.5,
|
|
7.5,
|
|
-11.0,
|
|
11.0,
|
|
8.75,
|
|
-8.75,
|
|
],
|
|
],
|
|
dtype=dtype,
|
|
)
|
|
val = torch.tensor(
|
|
[
|
|
[
|
|
0.25,
|
|
-0.5,
|
|
0.75,
|
|
-1.0,
|
|
1.25,
|
|
-1.5,
|
|
1.75,
|
|
-2.0,
|
|
2.25,
|
|
-2.5,
|
|
2.75,
|
|
-3.0,
|
|
3.25,
|
|
-3.5,
|
|
3.75,
|
|
-4.0,
|
|
],
|
|
[
|
|
-0.4,
|
|
0.6,
|
|
-0.8,
|
|
1.0,
|
|
-1.2,
|
|
1.4,
|
|
-1.6,
|
|
1.8,
|
|
-2.0,
|
|
2.2,
|
|
-2.4,
|
|
2.6,
|
|
-2.8,
|
|
3.0,
|
|
-3.2,
|
|
3.4,
|
|
],
|
|
],
|
|
dtype=dtype,
|
|
)
|
|
|
|
x = torch.cat((val, gate), dim=-1).contiguous()
|
|
kernel_out = torch.empty_like(val)
|
|
torch.ops._C.gelu_tanh_and_mul(kernel_out, x)
|
|
|
|
torch_ref = torch.nn.functional.gelu(val, approximate="tanh") * gate
|
|
|
|
atol = get_default_atol(kernel_out)
|
|
rtol = get_default_rtol(kernel_out)
|
|
torch.testing.assert_close(kernel_out, torch_ref, atol=atol, rtol=rtol)
|