test_compressed_tensors.py 9.51 KB
Newer Older
1
"""Test model set-up and weight loading for llmcompressor-quantized models.
2
3
4

Run `pytest tests/quantization/test_compressed_tensors.py`.
"""
5
from typing import Optional
6

7
import pytest
8
import torch
9
import os
10

11
from compressed_tensors.quantization import QuantizationType
12

13
from tests.models.utils import check_logprobs_close
14
from vllm.model_executor.layers.quantization.compressed_tensors.compressed_tensors import (  # noqa: E501
15
    CompressedTensorsLinearMethod, CompressedTensorsW4A16Sparse24,
16
    CompressedTensorsW8A8Fp8, CompressedTensorsW8A8Int8,
17
    CompressedTensorsW8A16Fp8, CompressedTensorsWNA16)
18
from ..utils import models_path_prefix
zhuwenwen's avatar
zhuwenwen committed
19
from vllm.platforms import current_platform
20
21


22
23
@pytest.mark.parametrize(
    "model_args",
zhuwenwen's avatar
zhuwenwen committed
24
    [(os.path.join(models_path_prefix, "nm-testing/tinyllama-oneshot-w8w8-test-static-shape-change"), "tensor",
25
      QuantizationType.INT, 2560, True),
zhuwenwen's avatar
zhuwenwen committed
26
     (os.path.join(models_path_prefix, "nm-testing/tinyllama-oneshot-w8-channel-a8-tensor"), "channel",
27
      QuantizationType.INT, 2560, True),
zhuwenwen's avatar
zhuwenwen committed
28
     (os.path.join(models_path_prefix, "nm-testing/asym-w8w8-int8-static-per-tensor-tiny-llama"), "tensor",
29
      QuantizationType.INT, 2560, False)])
30
def test_compressed_tensors_w8a8_static_setup(vllm_runner, model_args):
31
    model_path, strategy, quant_type, shape_0, is_symmetric = model_args
32
    with vllm_runner(model_path, enforce_eager=True) as llm:
33
34
        model = llm.model.llm_engine.model_executor.driver_worker.model_runner.model  # noqa: E501
        layer = model.model.layers[0]
35

36
37
38
39
        qkv_proj = layer.self_attn.qkv_proj
        o_proj = layer.self_attn.o_proj
        gate_up_proj = layer.mlp.gate_up_proj
        down_proj = layer.mlp.down_proj
40

41
42
43
44
45
46
47
48
49
50
51
52
        # assert zp for symmetric and asymmetric cases
        def zp_valid(zp: Optional[torch.Tensor]):
            if is_symmetric:
                return zp is None

            return zp is not None and zp.dtype is torch.int32

        assert zp_valid(qkv_proj.input_zero_point)
        assert zp_valid(o_proj.input_zero_point)
        assert zp_valid(gate_up_proj.input_zero_point)
        assert zp_valid(down_proj.input_zero_point)

53
54
55
56
57
58
        assert isinstance(qkv_proj.quant_method, CompressedTensorsLinearMethod)
        assert isinstance(o_proj.quant_method, CompressedTensorsLinearMethod)
        assert isinstance(gate_up_proj.quant_method,
                          CompressedTensorsLinearMethod)
        assert isinstance(down_proj.quant_method,
                          CompressedTensorsLinearMethod)
59
        assert isinstance(qkv_proj.scheme, CompressedTensorsW8A8Int8)
60

61
        assert qkv_proj.scheme.strategy == strategy
62
        assert qkv_proj.scheme.is_static_input_scheme
63
        expected_type = torch.int8
64
65
66
67

        assert qkv_proj.weight.dtype is expected_type
        assert o_proj.weight.dtype is expected_type
        assert gate_up_proj.weight.dtype is expected_type
68

69
        if qkv_proj.scheme.strategy == "tensor":
70
71
72
73
74
75
            # Make sure it is a channelwise buffer
            # After running process_weights_after_loading
            assert len(qkv_proj.weight_scale.shape) == 2
            assert qkv_proj.weight_scale.shape[0] == shape_0
            assert qkv_proj.weight_scale.shape[1] == 1
        assert qkv_proj.weight_scale.dtype is torch.float32
76
        assert qkv_proj.input_scale.dtype is torch.float32
77

78
        output = llm.generate_greedy(["Hello my name is"], max_tokens=20)
79
80
        assert output

81

82
83
84
@pytest.mark.parametrize(
    "model_path",
    [
zhuwenwen's avatar
zhuwenwen committed
85
        os.path.join(models_path_prefix, "neuralmagic/Llama-3.2-1B-quantized.w8a8")
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
        # TODO static & asymmetric
    ])
@pytest.mark.parametrize("max_tokens", [32])
@pytest.mark.parametrize("num_logprobs", [10])
def test_compressed_tensors_w8a8_logprobs(hf_runner, vllm_runner,
                                          example_prompts, model_path,
                                          max_tokens, num_logprobs):
    dtype = "bfloat16"

    with hf_runner(model_path, dtype=dtype) as hf_model:
        hf_outputs = hf_model.generate_greedy_logprobs_limit(
            example_prompts, max_tokens, num_logprobs)

    with vllm_runner(model_path, dtype=dtype) as vllm_model:
        vllm_outputs = vllm_model.generate_greedy_logprobs(
            example_prompts, max_tokens, num_logprobs)

    check_logprobs_close(
        outputs_0_lst=hf_outputs,
        outputs_1_lst=vllm_outputs,
        name_0="hf",
        name_1="vllm",
    )


111
def test_compressed_tensors_no_enforce_eager(vllm_runner):
112
    model_path = os.path.join(models_path_prefix, "nm-testing/tinyllama-oneshot-w8w8-test-static-shape-change")
113
    with vllm_runner(model_path) as llm:
114
        output = llm.generate_greedy("Hello my name is", max_tokens=20)
115
116
117
        assert output


118
@pytest.mark.parametrize("model_args", [
119
    (os.path.join(models_path_prefix, "nm-testing/tinyllama-oneshot-w8a8-dynamic-token-v2"), "tensor"),
zhuwenwen's avatar
zhuwenwen committed
120
121
122
    (os.path.join(models_path_prefix, "nm-testing/tinyllama-oneshot-w8a8-dynamic-token-v2-asym"), "tensor"),
    (os.path.join(models_path_prefix, "nm-testing/tinyllama-oneshot-w8a8-channel-dynamic-token-v2"), "channel"),
    (os.path.join(models_path_prefix, "nm-testing/tinyllama-oneshot-w8a8-channel-dynamic-token-v2-asym"),
123
     "channel"),
124
])
125
def test_compressed_tensors_w8a8_dynamic_per_token(vllm_runner, model_args):
126
    model_path, strategy = model_args
127
    with vllm_runner(model_path, dtype=torch.float16) as llm:
128
129
130
131
132
133
        model = llm.model.llm_engine.model_executor.driver_worker.model_runner.model  # noqa: E501
        layer = model.model.layers[0]

        qkv_proj = layer.self_attn.qkv_proj

        assert isinstance(qkv_proj.quant_method, CompressedTensorsLinearMethod)
134
        assert isinstance(qkv_proj.scheme, CompressedTensorsW8A8Int8)
135
        assert not qkv_proj.scheme.is_static_input_scheme
136
        assert qkv_proj.scheme.strategy == strategy
137
        assert qkv_proj.weight.dtype is torch.int8
138

139
        output = llm.generate_greedy(["Hello my name is"], max_tokens=20)
140
141
        assert output

142

zhuwenwen's avatar
zhuwenwen committed
143
@pytest.mark.skipif(current_platform(),
144
                    reason="WNA16 is not supported on ROCm.")
145
146
@pytest.mark.parametrize(
    "wNa16_args",
147
148
149
    [(os.path.join(models_path_prefix,"nm-testing/tinyllama-oneshot-w4a16-channel-v2"), "channel", None, 8),
     (os.path.join(models_path_prefix,"nm-testing/tinyllama-oneshot-w4a16-group128-v2"), "group", 128, 8),
     (os.path.join(models_path_prefix,"nm-testing/tinyllama-oneshot-w8a16-per-channel"), "channel", None, 4)])
150
def test_compressed_tensors_wNa16(vllm_runner, wNa16_args):
151
    model, strategy, group, pack_factor = wNa16_args
152
153
154
155
156
157
    with vllm_runner(model) as llm:
        model = llm.model.llm_engine.model_executor.driver_worker.model_runner.model  # noqa: E501
        layer = model.model.layers[0]

        qkv_proj = layer.self_attn.qkv_proj
        assert isinstance(qkv_proj.quant_method, CompressedTensorsLinearMethod)
158
        assert isinstance(qkv_proj.scheme, CompressedTensorsWNA16)
159
160

        assert qkv_proj.scheme.strategy == strategy
161
        assert qkv_proj.scheme.group_size == (-1 if group is None else group)
162
163
164

        assert qkv_proj.weight_packed.dtype is torch.int32
        assert qkv_proj.weight_scale.dtype is torch.float16
165
        assert qkv_proj.scheme.pack_factor == pack_factor
166

167
168
169
        output = llm.generate_greedy("Hello my name is", max_tokens=20)
        assert output

170

zhuwenwen's avatar
zhuwenwen committed
171
@pytest.mark.skipif(current_platform(),
172
                    reason="W4A16 MARLIN is not supported on ROCm.")
173
def test_compressed_tensors_w4a16_marlin24(vllm_runner):
174
    model_path = os.path.join(models_path_prefix,"nm-testing/llama7b-one-shot-2_4-w4a16-marlin24-t")
175
176
177
178
179
180
181
182
183
184
    with vllm_runner(model_path) as llm:
        model = llm.model.llm_engine.model_executor.driver_worker.model_runner.model  # noqa: E501
        layer = model.model.layers[0]

        qkv_proj = layer.self_attn.qkv_proj

        assert isinstance(qkv_proj.quant_method, CompressedTensorsLinearMethod)
        assert isinstance(qkv_proj.scheme, CompressedTensorsW4A16Sparse24)
        assert qkv_proj.weight_packed.dtype is torch.int32

185
        output = llm.generate_greedy("Hello my name is", max_tokens=20)
186
        assert output
187
188


zhuwenwen's avatar
zhuwenwen committed
189
@pytest.mark.skipif(current_platform(),
190
                    reason="FP8 is not supported on ROCm.")
191
def test_compressed_tensors_fp8(vllm_runner):
192
    model_path = os.path.join(models_path_prefix,"nm-testing/Meta-Llama-3-8B-FP8-compressed-tensors-test")
193
194
195
196
197
198
199
    with vllm_runner(model_path) as llm:
        model = llm.model.llm_engine.model_executor.driver_worker.model_runner.model  # noqa: E501
        layer = model.model.layers[0]

        qkv_proj = layer.self_attn.qkv_proj

        assert isinstance(qkv_proj.quant_method, CompressedTensorsLinearMethod)
200
201
202
203
        assert isinstance(
            qkv_proj.scheme,
            (CompressedTensorsW8A8Fp8, CompressedTensorsW8A16Fp8))

204
        assert qkv_proj.input_scale.dtype is torch.float32
205
206
207
208
209
210

        if isinstance(qkv_proj.scheme, CompressedTensorsW8A8Fp8):
            assert len(qkv_proj.input_scale.shape) == 0
            assert qkv_proj.weight.dtype is torch.float8_e4m3fn
            assert qkv_proj.weight_scale.dtype is torch.float32
            assert len(qkv_proj.weight_scale.shape) == 0
211

212
        output = llm.generate_greedy("Hello my name is", max_tokens=20)
213
        assert output
214
215


zhuwenwen's avatar
zhuwenwen committed
216
@pytest.mark.skipif(current_platform(),
217
                    reason="FP8 KV cache is not supported on ROCm.")
218
def test_compressed_tensors_kv_cache(vllm_runner):
219
    model_path = os.path.join(models_path_prefix,"nm-testing/TinyLlama-1.1B-compressed-tensors-kv-cache-scheme")
220
221
    with vllm_runner(model_path, kv_cache_dtype="fp8") as llm:
        output = llm.generate_greedy("Hello world!", max_tokens=20)
222
        assert output