@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 4671ac6e2a
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 15, 04:45 UTC

[Bugfix][Benchmark] Fix Marlin benchmark (#19929)

22quinn committed Jun 23, 2025 at 15:25 UTC 4671ac6e2ae9975ac305f767fc21e47d6ffde448
1 file changed +150 -79
benchmarks/kernels/benchmark_marlin.py
+150 -79
@@ -22,8 +22,16 @@ from vllm.model_executor.layers.quantization.utils.marlin_utils import (
22 MARLIN_SUPPORTED_GROUP_SIZES,
23 query_marlin_supported_quant_types,
24 )
25 +from vllm.model_executor.layers.quantization.utils.marlin_utils_fp4 import (
26 + FP4_MARLIN_SUPPORTED_GROUP_SIZES,
27 + rand_marlin_weight_fp4_like,
28 +)
29 +from vllm.model_executor.layers.quantization.utils.marlin_utils_fp8 import (
30 + marlin_quant_fp8_torch,
31 +)
32 from vllm.model_executor.layers.quantization.utils.marlin_utils_test import (
33 MarlinWorkspace,
34 + awq_marlin_quantize,
35 marlin_quantize,
36 )
37 from vllm.model_executor.layers.quantization.utils.marlin_utils_test_24 import (
@@ -35,7 +43,7 @@ from vllm.model_executor.layers.quantization.utils.quant_utils import (
43 quantize_weights,
44 sort_weights,
45 )
38 -from vllm.scalar_type import ScalarType
46 +from vllm.scalar_type import ScalarType, scalar_types
47 from vllm.utils import FlexibleArgumentParser
48
49 DEFAULT_MODELS = ["meta-llama/Llama-2-7b-hf/TP1"]
@@ -57,80 +65,144 @@ def bench_run(
65 size_n: int,
66 ):
67 label = "Quant Matmul"
60 -
68 sub_label = "{}, act={} k_full={}, q={}, g={}, MKN=({}x{}x{})".format(
69 model, act_order, is_k_full, str(quant_type), group_size, size_m, size_k, size_n
70 )
64 -
71 print(f"Testing: {sub_label}")
72
73 a = torch.randn(size_m, size_k).to(torch.half).cuda()
74 b = torch.rand(size_k, size_n).to(torch.half).cuda()
75 + has_zp = quant_type in [scalar_types.uint4, scalar_types.uint8]
76 + if act_order and (group_size == -1 or group_size == size_k or has_zp):
77 + return
78 + if size_k % group_size != 0:
79 + return
80
70 - a_tmp = torch.zeros(size_m, size_k).to(torch.half).cuda()
81 + marlin_24_supported = (
82 + quant_type in GPTQ_MARLIN_24_SUPPORTED_QUANT_TYPES
83 + and group_size in GPTQ_MARLIN_24_SUPPORTED_GROUP_SIZES
84 + )
85 + repack_supported = (
86 + quant_type in GPTQ_MARLIN_24_SUPPORTED_QUANT_TYPES
87 + and group_size in MARLIN_SUPPORTED_GROUP_SIZES
88 + )
89 + allspark_supported = (
90 + quant_type in ALLSPARK_SUPPORTED_QUANT_TYPES
91 + and group_size == -1
92 + and not act_order
93 + and is_k_full
94 + )
95 +
96 + def gen_marlin_params():
97 + # Marlin quant
98 + marlin_g_idx = marlin_sort_indices = marlin_zp = marlin_s2 = None
99 + if quant_type == scalar_types.float4_e2m1f:
100 + if group_size != 16 or act_order:
101 + return
102 + marlin_w_ref, marlin_q_w, marlin_s, marlin_s2 = rand_marlin_weight_fp4_like(
103 + b.T, group_size
104 + )
105 + elif quant_type == scalar_types.float8_e4m3fn:
106 + if group_size not in [-1, 128] or act_order:
107 + return
108 + marlin_w_ref, marlin_q_w, marlin_s = marlin_quant_fp8_torch(b.T, group_size)
109 + elif group_size == 16:
110 + return
111 + elif has_zp:
112 + marlin_w_ref, marlin_q_w, marlin_s, marlin_zp = awq_marlin_quantize(
113 + b, quant_type, group_size
114 + )
115 + else:
116 + marlin_w_ref, marlin_q_w, marlin_s, marlin_g_idx, marlin_sort_indices, _ = (
117 + marlin_quantize(b, quant_type, group_size, act_order)
118 + )
119 + return (
120 + marlin_w_ref,
121 + marlin_q_w,
122 + marlin_s,
123 + marlin_s2,
124 + marlin_zp,
125 + marlin_g_idx,
126 + marlin_sort_indices,
127 + )
128 +
129 + def gen_marlin_24_params():
130 + marlin_24_w_ref = marlin_24_q_w_comp = marlin_24_meta = marlin_24_s = None
131 + if marlin_24_supported:
132 + (marlin_24_w_ref, marlin_24_q_w_comp, marlin_24_meta, marlin_24_s) = (
133 + marlin_24_quantize(b, quant_type, group_size)
134 + )
135 + return (marlin_24_w_ref, marlin_24_q_w_comp, marlin_24_meta, marlin_24_s)
136 +
137 + def gen_repack_params():
138 + q_w_gptq = None
139 + repack_sort_indices = None
140 + if repack_supported:
141 + (w_ref, q_w, s, g_idx, rand_perm) = gptq_quantize_weights(
142 + b, quant_type, group_size, act_order
143 + )
144 + q_w_gptq = gptq_pack(q_w, quant_type.size_bits, size_k, size_n)
145 +
146 + # For act_order, sort the "weights" and "g_idx"
147 + # so that group ids are increasing
148 + repack_sort_indices = torch.empty(0, dtype=torch.int, device=b.device)
149 + if act_order:
150 + (q_w, g_idx, repack_sort_indices) = sort_weights(q_w, g_idx)
151 + return q_w_gptq, repack_sort_indices
152 +
153 + def gen_allspark_params():
154 + qw_reorder = s_reorder = zp_reorder = sm_count = sm_version = (
155 + CUBLAS_M_THRESHOLD
156 + ) = None
157 + nonlocal allspark_supported
158 + if allspark_supported:
159 + properties = torch.cuda.get_device_properties(b.device.index)
160 + sm_count = properties.multi_processor_count
161 + sm_version = properties.major * 10 + properties.minor
162 +
163 + supported_arch = sm_version >= 80 and sm_version < 90
164 + allspark_supported = allspark_supported and supported_arch
165 + if supported_arch:
166 + w_ref, qw, s, zp = quantize_weights(b, quant_type, group_size, has_zp)
167 + qw = qw.to(torch.uint8)
168 +
169 + qw_reorder, s_reorder, zp_reorder = ops.allspark_repack_weight(
170 + qw, s, zp, has_zp
171 + )
172 + CUBLAS_M_THRESHOLD = ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD
173 + return (
174 + qw_reorder,
175 + s_reorder,
176 + zp_reorder,
177 + sm_count,
178 + sm_version,
179 + CUBLAS_M_THRESHOLD,
180 + )
181
72 - # Marlin quant
182 (
183 marlin_w_ref,
184 marlin_q_w,
185 marlin_s,
186 + marlin_s2,
187 + marlin_zp,
188 marlin_g_idx,
189 marlin_sort_indices,
79 - marlin_rand_perm,
80 - ) = marlin_quantize(b, quant_type, group_size, act_order)
81 -
82 - # Marlin_24 quant
83 - (marlin_24_w_ref, marlin_24_q_w_comp, marlin_24_meta, marlin_24_s) = (
84 - marlin_24_quantize(b, quant_type, group_size)
190 + ) = gen_marlin_params()
191 + marlin_24_w_ref, marlin_24_q_w_comp, marlin_24_meta, marlin_24_s = (
192 + gen_marlin_24_params()
193 )
86 -
87 - marlin_zp = torch.empty(0, dtype=torch.int, device=b.device)
88 -
89 - # GPTQ quant
90 - (w_ref, q_w, s, g_idx, rand_perm) = gptq_quantize_weights(
91 - b, quant_type, group_size, act_order
194 + q_w_gptq, repack_sort_indices = gen_repack_params()
195 + qw_reorder, s_reorder, zp_reorder, sm_count, sm_version, CUBLAS_M_THRESHOLD = (
196 + gen_allspark_params()
197 )
93 - q_w_gptq = gptq_pack(q_w, quant_type.size_bits, size_k, size_n)
94 -
95 - # For act_order, sort the "weights" and "g_idx"
96 - # so that group ids are increasing
97 - repack_sort_indices = torch.empty(0, dtype=torch.int, device=b.device)
98 - if act_order:
99 - (q_w, g_idx, repack_sort_indices) = sort_weights(q_w, g_idx)
198
199 # Prepare
200 marlin_workspace = MarlinWorkspace(
201 size_n, GPTQ_MARLIN_MIN_THREAD_N, GPTQ_MARLIN_MAX_PARALLEL
202 )
105 -
203 marlin_24_workspace = MarlinWorkspace(
204 size_n, GPTQ_MARLIN_24_MIN_THREAD_N, GPTQ_MARLIN_24_MAX_PARALLEL
205 )
109 - marlin_zp = torch.zeros_like(marlin_s, dtype=torch.int)
110 -
111 - # AllSpark W8A16 quant
112 - as_supported_case = (
113 - quant_type in ALLSPARK_SUPPORTED_QUANT_TYPES
114 - and group_size == -1
115 - and not act_order
116 - and is_k_full
117 - )
118 - if as_supported_case:
119 - properties = torch.cuda.get_device_properties(b.device.index)
120 - sm_count = properties.multi_processor_count
121 - sm_version = properties.major * 10 + properties.minor
122 -
123 - supported_arch = sm_version >= 80 and sm_version < 90
124 - as_supported_case = as_supported_case and supported_arch
125 - if supported_arch:
126 - has_zp = False
127 - w_ref, qw, s, zp = quantize_weights(b, quant_type, group_size, has_zp)
128 - qw = qw.to(torch.uint8)
129 -
130 - qw_reorder, s_reorder, zp_reorder = ops.allspark_repack_weight(
131 - qw, s, zp, has_zp
132 - )
133 - CUBLAS_M_THRESHOLD = ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD
206
207 globals = {
208 # Gen params
@@ -140,15 +212,14 @@ def bench_run(
212 "size_n": size_n,
213 "size_k": size_k,
214 "a": a,
143 - "a_tmp": a_tmp,
215 # Marlin params
216 "marlin_w_ref": marlin_w_ref,
217 "marlin_q_w": marlin_q_w,
218 "marlin_s": marlin_s,
219 + "marlin_s2": marlin_s2,
220 "marlin_zp": marlin_zp,
221 "marlin_g_idx": marlin_g_idx,
222 "marlin_sort_indices": marlin_sort_indices,
151 - "marlin_rand_perm": marlin_rand_perm,
223 "marlin_workspace": marlin_workspace,
224 "is_k_full": is_k_full,
225 # Marlin_24 params
@@ -161,12 +232,12 @@ def bench_run(
232 "q_w_gptq": q_w_gptq,
233 "repack_sort_indices": repack_sort_indices,
234 # AllSpark W8A16 params
164 - "qw_reorder": qw_reorder if as_supported_case else None,
165 - "s_reorder": s_reorder if as_supported_case else None,
166 - "zp_reorder": zp_reorder if as_supported_case else None,
167 - "sm_count": sm_count if as_supported_case else None,
168 - "sm_version": sm_version if as_supported_case else None,
169 - "CUBLAS_M_THRESHOLD": CUBLAS_M_THRESHOLD if as_supported_case else None,
235 + "qw_reorder": qw_reorder,
236 + "s_reorder": s_reorder,
237 + "zp_reorder": zp_reorder,
238 + "sm_count": sm_count,
239 + "sm_version": sm_version,
240 + "CUBLAS_M_THRESHOLD": CUBLAS_M_THRESHOLD,
241 # Kernels
242 "gptq_marlin_gemm": ops.gptq_marlin_gemm,
243 "gptq_marlin_24_gemm": ops.gptq_marlin_24_gemm,
@@ -177,7 +248,7 @@ def bench_run(
248 min_run_time = 1
249
250 # Warmup pytorch
180 - for i in range(5):
251 + for _ in range(5):
252 torch.matmul(a, marlin_w_ref)
253
254 results.append(
@@ -192,17 +263,17 @@ def bench_run(
263
264 results.append(
265 benchmark.Timer(
195 - stmt="output = gptq_marlin_gemm(a, marlin_q_w, marlin_s, marlin_zp, marlin_g_idx, marlin_sort_indices, marlin_workspace.scratch, quant_type, size_m, size_n, size_k, is_k_full, False, False, False)", # noqa: E501
266 + stmt="output = gptq_marlin_gemm(a, None, marlin_q_w, marlin_s, marlin_s2, marlin_zp, marlin_g_idx, marlin_sort_indices, marlin_workspace.scratch, quant_type, size_m, size_n, size_k, is_k_full, False, False, False)", # noqa: E501
267 globals=globals,
268 label=label,
269 sub_label=sub_label,
199 - description="gptq_marlin_gemm_fp16",
270 + description="gptq_marlin_gemm",
271 ).blocked_autorange(min_run_time=min_run_time)
272 )
273
274 results.append(
275 benchmark.Timer(
205 - stmt="output = gptq_marlin_gemm(a, marlin_q_w, marlin_s, marlin_zp, marlin_g_idx, marlin_sort_indices, marlin_workspace.scratch, quant_type, size_m, size_n, size_k, is_k_full, False, True, False)", # noqa: E501
276 + stmt="output = gptq_marlin_gemm(a, None, marlin_q_w, marlin_s, marlin_s2, marlin_zp, marlin_g_idx, marlin_sort_indices, marlin_workspace.scratch, quant_type, size_m, size_n, size_k, is_k_full, False, True, False)", # noqa: E501
277 globals=globals,
278 label=label,
279 sub_label=sub_label,
@@ -210,10 +281,7 @@ def bench_run(
281 ).blocked_autorange(min_run_time=min_run_time)
282 )
283
213 - if (
214 - quant_type in GPTQ_MARLIN_24_SUPPORTED_QUANT_TYPES
215 - and group_size in GPTQ_MARLIN_24_SUPPORTED_GROUP_SIZES
216 - ):
284 + if marlin_24_supported:
285 results.append(
286 benchmark.Timer(
287 stmt="output = gptq_marlin_24_gemm(a, marlin_24_q_w_comp, marlin_24_meta, marlin_24_s, marlin_24_workspace.scratch, quant_type, size_m, size_n, size_k)", # noqa: E501
@@ -224,17 +292,18 @@ def bench_run(
292 ).blocked_autorange(min_run_time=min_run_time)
293 )
294
227 - results.append(
228 - benchmark.Timer(
229 - stmt="q_res = gptq_marlin_repack(q_w_gptq, repack_sort_indices, size_k, size_n, quant_type.size_bits)", # noqa: E501
230 - globals=globals,
231 - label=label,
232 - sub_label=sub_label,
233 - description="gptq_marlin_repack",
234 - ).blocked_autorange(min_run_time=min_run_time)
235 - )
295 + if repack_supported:
296 + results.append(
297 + benchmark.Timer(
298 + stmt="q_res = gptq_marlin_repack(q_w_gptq, repack_sort_indices, size_k, size_n, quant_type.size_bits)", # noqa: E501
299 + globals=globals,
300 + label=label,
301 + sub_label=sub_label,
302 + description="gptq_marlin_repack",
303 + ).blocked_autorange(min_run_time=min_run_time)
304 + )
305
237 - if as_supported_case:
306 + if allspark_supported:
307 results.append(
308 benchmark.Timer(
309 stmt="output = allspark_w8a16_gemm(a, qw_reorder, s_reorder, zp_reorder, size_n, group_size, sm_count, sm_version, CUBLAS_M_THRESHOLD, False, True)", # noqa: E501
@@ -250,7 +319,6 @@ def main(args):
319 print("Benchmarking models:")
320 for i, model in enumerate(args.models):
321 print(f"[{i}] {model}")
253 -
322 results: list[benchmark.Measurement] = []
323
324 for model in args.models:
@@ -278,14 +346,17 @@ def main(args):
346 ):
347 continue
348
281 - for quant_type in query_marlin_supported_quant_types(False):
349 + for quant_type in query_marlin_supported_quant_types():
350 if (
351 len(args.limit_num_bits) > 0
352 and quant_type.size_bits not in args.limit_num_bits
353 ):
354 continue
355
288 - for group_size in MARLIN_SUPPORTED_GROUP_SIZES:
356 + for group_size in (
357 + MARLIN_SUPPORTED_GROUP_SIZES
358 + + FP4_MARLIN_SUPPORTED_GROUP_SIZES
359 + ):
360 if (
361 len(args.limit_group_size) > 0
362 and group_size not in args.limit_group_size