[Kernel] Remove AllSpark INT8 W8A16 GEMM backend (#58001)

Signed-off-by: mgoin <mgoin64@gmail.com>

Misha Goin committed Sep 22, 2026 at 17:07 UTC 25965ee583b154c0ce356466d4cf2d25f6815c60
13 files changed -2104
CMakeLists.txt
-16
@@ -777,22 +777,6 @@ if(VLLM_GPU_LANG STREQUAL "CUDA" OR VLLM_GPU_LANG STREQUAL "HIP")
777 "(requires SM90+ and CUDA >= 12.0).")
778 endif()
779
780 - # Only build AllSpark kernels if we are building for at least some compatible archs.
781 - cuda_archs_loose_intersection(ALLSPARK_ARCHS "8.0;8.6;8.7;8.9" "${CUDA_ARCHS}")
782 - if (ALLSPARK_ARCHS)
783 - set(ALLSPARK_SRCS
784 - "csrc/libtorch_stable/quantization/gptq_allspark/allspark_repack.cu"
785 - "csrc/libtorch_stable/quantization/gptq_allspark/allspark_qgemm_w8a16.cu")
786 - set_gencode_flags_for_srcs(
787 - SRCS "${ALLSPARK_SRCS}"
788 - CUDA_ARCHS "${ALLSPARK_ARCHS}")
789 - list(APPEND VLLM_STABLE_EXT_SRC "${ALLSPARK_SRCS}")
790 - message(STATUS "Building AllSpark kernels for archs: ${ALLSPARK_ARCHS}")
791 - else()
792 - message(STATUS "Not building AllSpark kernels as no compatible archs found"
793 - " in CUDA target architectures")
794 - endif()
795 -
780 #
781 # CUTLASS scaled_mm kernels (moved from _C to _C_stable_libtorch)
782 #
benchmarks/kernels/benchmark_marlin.py
-59
@@ -6,10 +6,6 @@ import torch.utils.benchmark as benchmark
6 from benchmark_shapes import WEIGHT_SHAPES
7
8 from vllm import _custom_ops as ops
9 -from vllm.model_executor.layers.quantization.utils.allspark_utils import (
10 - ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD,
11 - ALLSPARK_SUPPORTED_QUANT_TYPES,
12 -)
9 from vllm.model_executor.layers.quantization.utils.marlin_utils import (
10 GPTQ_MARLIN_MAX_PARALLEL,
11 GPTQ_MARLIN_MIN_THREAD_N,
@@ -31,7 +27,6 @@ from vllm.model_executor.layers.quantization.utils.marlin_utils_test import (
27 from vllm.model_executor.layers.quantization.utils.quant_utils import (
28 gptq_pack,
29 gptq_quantize_weights,
34 - quantize_weights,
30 )
31 from vllm.scalar_type import ScalarType, scalar_types
32 from vllm.utils.argparse_utils import FlexibleArgumentParser
@@ -62,9 +57,6 @@ def bench_run(
57 return
58
59 repack_supported = group_size in MARLIN_SUPPORTED_GROUP_SIZES
65 - allspark_supported = (
66 - quant_type in ALLSPARK_SUPPORTED_QUANT_TYPES and group_size == -1
67 - )
60
61 def gen_marlin_params():
62 # Marlin quant
@@ -104,35 +96,6 @@ def bench_run(
96 q_w_gptq = gptq_pack(q_w, quant_type.size_bits, size_k, size_n)
97 return q_w_gptq
98
107 - def gen_allspark_params():
108 - qw_reorder = s_reorder = zp_reorder = sm_count = sm_version = (
109 - CUBLAS_M_THRESHOLD
110 - ) = None
111 - nonlocal allspark_supported
112 - if allspark_supported:
113 - properties = torch.cuda.get_device_properties(b.device.index)
114 - sm_count = properties.multi_processor_count
115 - sm_version = properties.major * 10 + properties.minor
116 -
117 - supported_arch = sm_version >= 80 and sm_version < 90
118 - allspark_supported = allspark_supported and supported_arch
119 - if supported_arch:
120 - w_ref, qw, s, zp = quantize_weights(b, quant_type, group_size, has_zp)
121 - qw = qw.to(torch.uint8)
122 -
123 - qw_reorder, s_reorder, zp_reorder = ops.allspark_repack_weight(
124 - qw, s, zp, has_zp
125 - )
126 - CUBLAS_M_THRESHOLD = ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD
127 - return (
128 - qw_reorder,
129 - s_reorder,
130 - zp_reorder,
131 - sm_count,
132 - sm_version,
133 - CUBLAS_M_THRESHOLD,
134 - )
135 -
99 (
100 marlin_w_ref,
101 marlin_q_w,
@@ -141,9 +104,6 @@ def bench_run(
104 marlin_zp,
105 ) = gen_marlin_params()
106 q_w_gptq = gen_repack_params()
144 - qw_reorder, s_reorder, zp_reorder, sm_count, sm_version, CUBLAS_M_THRESHOLD = (
145 - gen_allspark_params()
146 - )
107
108 # Prepare
109 marlin_workspace = MarlinWorkspace(
@@ -167,17 +127,9 @@ def bench_run(
127 "marlin_workspace": marlin_workspace,
128 # GPTQ params
129 "q_w_gptq": q_w_gptq,
170 - # AllSpark W8A16 params
171 - "qw_reorder": qw_reorder,
172 - "s_reorder": s_reorder,
173 - "zp_reorder": zp_reorder,
174 - "sm_count": sm_count,
175 - "sm_version": sm_version,
176 - "CUBLAS_M_THRESHOLD": CUBLAS_M_THRESHOLD,
130 # Kernels
131 "marlin_gemm": ops.marlin_gemm,
132 "gptq_marlin_repack": ops.gptq_marlin_repack,
180 - "allspark_w8a16_gemm": ops.allspark_w8a16_gemm,
133 }
134
135 min_run_time = 1
@@ -227,17 +179,6 @@ def bench_run(
179 ).blocked_autorange(min_run_time=min_run_time)
180 )
181
230 - if allspark_supported:
231 - results.append(
232 - benchmark.Timer(
233 - 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
234 - globals=globals,
235 - label=label,
236 - sub_label=sub_label,
237 - description="allspark_w8a16_gemm_fp32",
238 - ).blocked_autorange(min_run_time=min_run_time)
239 - )
240 -
182
183 def main(args):
184 print("Benchmarking models:")
csrc/libtorch_stable/ops.h
-3
@@ -175,9 +175,6 @@ torch::stable::Tensor awq_dequantize(torch::stable::Tensor _kernel,
175 // DSV3 fused A GEMM: conditionally compiled so declaration and impl
176 // registration are in the source file (dsv3_fused_a_gemm.cu)
177
178 -// AllSpark ops: declarations are in the source files
179 -// (allspark_repack.cu and allspark_qgemm_w8a16.cu)
180 -
178 #endif
179
180 // CPU tensor -> CUDA UVA view (shared CUDA/ROCm)
csrc/libtorch_stable/quantization/gptq_allspark/allspark_qgemm_w8a16.cu deleted
-1024
@@ -1,1024 +0,0 @@
1 -#include "allspark_utils.cuh"
2 -
3 -#include <torch/csrc/stable/c/shim.h>
4 -#include <torch/csrc/stable/library.h>
5 -#include <torch/csrc/stable/tensor.h>
6 -#include <torch/headeronly/core/ScalarType.h>
7 -
8 -#include <cublas_v2.h>
9 -
10 -#include "core/registration.h"
11 -#include "libtorch_stable/torch_utils.h"
12 -
13 -torch::stable::Tensor as_g_workspace;
14 -
15 -#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
16 -
17 -torch::stable::Tensor allspark_w8a16_gemm(
18 - torch::stable::Tensor const& a, torch::stable::Tensor const& b_qweight,
19 - torch::stable::Tensor const& b_scales,
20 - std::optional<torch::stable::Tensor> const& b_qzeros, int64_t n,
21 - int64_t group_size, int64_t sm_count, int64_t sm_version,
22 - int64_t CUBLAS_M_THRESHOLD, bool has_zp, bool n32k16_reorder) {
23 - STD_TORCH_CHECK_NOT_IMPLEMENTED(
24 - false, "allspark_w8a16_gemm(..) requires CUDA_ARCH >= 8.0");
25 - return torch::stable::empty({1, 1});
26 -}
27 -
28 -#else
29 -namespace allspark {
30 -/*
31 - * GemmTile manage data movement from Global Memory to Shared Memory
32 - * requiring N % 8 == 0, K % 16 == 0 by loading uint
33 - * BN is obtained by padding the original N to a multiple of 32
34 - * weight B is rearranged as N32K16 order,
35 - * i.e. a initial data block of size 32(n)x16(k) is reordered as n8k4n4k4,
36 - * in order to put data loaded by the same thread of 32x16 data block together
37 - * continuously (see
38 - * https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#matrix-fragments-for-mma-m16n8k16-with-floating-point-type)
39 - */
40 -template <typename FType, typename QType, int Mtile, int Ntile, int NStage,
41 - int BLOCK>
42 -struct GmemTile_W8A16_PerC_MtilexNtilex32_multistage_SM8x_SplitK {
43 - // element num loaded by a LDG inst.
44 - static constexpr int LDG_ELEMENT_CNT_A = 8;
45 - static constexpr int LDG_ELEMENT_CNT_B = 16;
46 - static constexpr int WARP_SIZE = 32;
47 - static constexpr int M_SIZE_ONE_LOAD = (BLOCK * LDG_ELEMENT_CNT_A) / 32;
48 - static constexpr int N_SIZE_ONE_LOAD = (BLOCK * LDG_ELEMENT_CNT_B) / 32;
49 -
50 - __device__ GmemTile_W8A16_PerC_MtilexNtilex32_multistage_SM8x_SplitK(
51 - const SM8x_GEMM_W8A16_Splitk_Params<FType, QType>& k_params,
52 - const uint32_t& A_smem_addr, const uint32_t& BQ_smem_addr,
53 - const uint32_t& A_stage_stride, const uint32_t& BQ_stage_stride)
54 - : params(k_params),
55 - A_smem_base_addr(A_smem_addr),
56 - BQ_smem_base_addr(BQ_smem_addr),
57 - A_smem_stage_stride(A_stage_stride),
58 - BQ_smem_stage_stride(BQ_stage_stride) {
59 - this_block_A_base_ptr = params.A_ptr + blockIdx.x * Mtile * params.K +
60 - blockIdx.z * params.SplitK;
61 - // here B is rearranged as N32K16 order, i.e. 4 continuous N-direction
62 - // 8(N)x16(K) size data blocks are packed together
63 - this_block_B_base_ptr = params.B_ptr + blockIdx.y * Ntile * params.K +
64 - blockIdx.z * params.SplitK * 4;
65 -
66 - const auto lane_id = threadIdx.x % WARP_SIZE;
67 -
68 - // For matrix A, a block load/store Mtile(row) x 32(col) elements in
69 - // multiple iters, 8x4 warp load/store 8(row) x 32(col) elements per iter
70 - const auto Aldg_row_base_idx = threadIdx.x / 4;
71 - Aldg_col_idx = (threadIdx.x % 4) * LDG_ELEMENT_CNT_A;
72 - const int Aldg_base_offset = Aldg_row_base_idx * params.K + Aldg_col_idx;
73 -
74 - // For matrix B, a block load/store elements of (Ntile / 4) row x 128 col
75 - // elements of N32K16 packing in multiple iters, 4x8 warp load/store 4(row)
76 - // * 128(col) per iter
77 - Bldg_col_idx = (threadIdx.x % 8) * LDG_ELEMENT_CNT_B;
78 - const auto Bldg_row_base_idx = threadIdx.x / 8;
79 - const int Bldg_base_offset =
80 - Bldg_row_base_idx * params.K * 4 + Bldg_col_idx;
81 -
82 - this_block_A_base_ptr += Aldg_base_offset;
83 - this_block_B_base_ptr += Bldg_base_offset;
84 -
85 - const int sts_a_base_offset =
86 - (threadIdx.x / 4) * 32 +
87 - ((lane_id % 4) ^ ((lane_id / 4) % 4) ^ ((lane_id / 4) / 4)) *
88 - LDG_ELEMENT_CNT_A;
89 - const int sts_bq_base_offset =
90 - Bldg_row_base_idx * 32 * 4 +
91 - ((threadIdx.x % 8) ^ (((threadIdx.x / 8) % 2) * 4)) * LDG_ELEMENT_CNT_B;
92 -
93 - A_smem_base_addr += sts_a_base_offset * sizeof(FType);
94 - BQ_smem_base_addr += sts_bq_base_offset * sizeof(uint8_t);
95 -
96 - A_ldg_guard = 0;
97 - B_ldg_guard = 0;
98 - #pragma unroll
99 - for (int i = 0; i < (Mtile + M_SIZE_ONE_LOAD - 1) / M_SIZE_ONE_LOAD; ++i) {
100 - auto m_idx = blockIdx.x * Mtile + Aldg_row_base_idx + i * M_SIZE_ONE_LOAD;
101 - if (m_idx < params.M) {
102 - A_ldg_guard |= (1u << i);
103 - }
104 - }
105 -
106 - const int N_padded = (params.N + 31) / 32 * 32;
107 - #pragma unroll
108 - for (int i = 0; i < (Ntile + N_SIZE_ONE_LOAD - 1) / N_SIZE_ONE_LOAD; ++i) {
109 - auto n_idx = blockIdx.y * Ntile + (Bldg_row_base_idx / 8) * 32 +
110 - i * N_SIZE_ONE_LOAD;
111 - if (n_idx < N_padded) {
112 - B_ldg_guard |= (1u << i);
113 - }
114 - }
115 - }
116 -
117 - __device__ void ldgsts_first_ktiles(const int& first_k_tile,
118 - const int& k_tiles) {
119 - // load first k_tile
120 - // load A
121 - const int A_src_size = Aldg_col_idx < first_k_tile ? 16 : 0;
122 - #pragma unroll
123 - for (int i = 0; i < (Mtile + M_SIZE_ONE_LOAD - 1) / M_SIZE_ONE_LOAD; ++i) {
124 - cp_async<16>(
125 - A_smem_base_addr + (i * M_SIZE_ONE_LOAD * 32) * sizeof(FType),
126 - this_block_A_base_ptr + i * M_SIZE_ONE_LOAD * params.K, A_src_size,
127 - (A_ldg_guard & (1u << i)) != 0);
128 - }
129 -
130 - // load B
131 - const int B_src_size = (Bldg_col_idx / 4) < first_k_tile ? 16 : 0;
132 - #pragma unroll
133 - for (int i = 0; i < (Ntile + N_SIZE_ONE_LOAD - 1) / N_SIZE_ONE_LOAD; ++i) {
134 - cp_async<16>(
135 - BQ_smem_base_addr + (i * N_SIZE_ONE_LOAD * 32) * sizeof(uint8_t),
136 - this_block_B_base_ptr + i * N_SIZE_ONE_LOAD * params.K, B_src_size,
137 - (B_ldg_guard & (1u << i)) != 0);
138 - }
139 -
140 - cp_async_commit_group();
141 - this_block_A_base_ptr += first_k_tile;
142 - this_block_B_base_ptr += (first_k_tile * 4);
143 -
144 - // load second to (N-stage - 1) k_tiles
145 - for (int stage_idx = 1; stage_idx < NStage - 1; ++stage_idx) {
146 - if (stage_idx < k_tiles) {
147 - #pragma unroll
148 - for (int i = 0; i < (Mtile + M_SIZE_ONE_LOAD - 1) / M_SIZE_ONE_LOAD;
149 - ++i) {
150 - cp_async<16>(A_smem_base_addr + stage_idx * A_smem_stage_stride +
151 - (i * M_SIZE_ONE_LOAD * 32) * sizeof(FType),
152 - this_block_A_base_ptr + i * M_SIZE_ONE_LOAD * params.K,
153 - 16, (A_ldg_guard & (1u << i)) != 0);
154 - }
155 -
156 - #pragma unroll
157 - for (int i = 0; i < (Ntile + N_SIZE_ONE_LOAD - 1) / N_SIZE_ONE_LOAD;
158 - ++i) {
159 - cp_async<16>(BQ_smem_base_addr + stage_idx * BQ_smem_stage_stride +
160 - (i * N_SIZE_ONE_LOAD * 32) * sizeof(uint8_t),
161 - this_block_B_base_ptr + i * N_SIZE_ONE_LOAD * params.K,
162 - 16, (B_ldg_guard & (1u << i)) != 0);
163 - }
164 -
165 - this_block_A_base_ptr += 32;
166 - this_block_B_base_ptr += (32 * 4);
167 - }
168 - cp_async_commit_group();
169 - }
170 - }
171 -
172 - __device__ void ldgsts(const int& sts_stage_idx) {
173 - const int a_stage_offset = sts_stage_idx * A_smem_stage_stride;
174 - const int bq_stage_offset = sts_stage_idx * BQ_smem_stage_stride;
175 - #pragma unroll
176 - for (int i = 0; i < (Mtile + M_SIZE_ONE_LOAD - 1) / M_SIZE_ONE_LOAD; ++i) {
177 - cp_async<16>(A_smem_base_addr + a_stage_offset +
178 - (i * M_SIZE_ONE_LOAD * 32) * sizeof(FType),
179 - this_block_A_base_ptr + i * M_SIZE_ONE_LOAD * params.K, 16,
180 - (A_ldg_guard & (1u << i)) != 0);
181 - }
182 -
183 - #pragma unroll
184 - for (int i = 0; i < (Ntile + N_SIZE_ONE_LOAD - 1) / N_SIZE_ONE_LOAD; ++i) {
185 - cp_async<16>(BQ_smem_base_addr + bq_stage_offset +
186 - (i * N_SIZE_ONE_LOAD * 32) * sizeof(uint8_t),
187 - this_block_B_base_ptr + i * N_SIZE_ONE_LOAD * params.K, 16,
188 - (B_ldg_guard & (1u << i)) != 0);
189 - }
190 -
191 - cp_async_commit_group();
192 - this_block_A_base_ptr += 32;
193 - this_block_B_base_ptr += (32 * 4);
194 - }
195 -
196 - const FType* this_block_A_base_ptr = nullptr;
197 - const QType* this_block_B_base_ptr = nullptr;
198 -
199 - int Aldg_col_idx;
200 - int Bldg_col_idx;
201 -
202 - uint32_t A_ldg_guard;
203 - uint32_t B_ldg_guard;
204 -
205 - uint32_t A_smem_base_addr, BQ_smem_base_addr;
206 - const uint32_t A_smem_stage_stride, BQ_smem_stage_stride;
207 -
208 - const SM8x_GEMM_W8A16_Splitk_Params<FType, QType>& params;
209 -};
210 -
211 -/*
212 - * requiring N % 8 == 0
213 - */
214 -template <typename FType, typename QType, int Mtile, int Ntile, int BLOCK,
215 - bool EnableFuse, bool has_zp>
216 -struct ComputeTile_W8A16_PerC_MtilexNtilex32_multistage_SM8x_SplitK {
217 - static constexpr int WARP_SIZE = 32;
218 - static constexpr int WARP_CNT = BLOCK / WARP_SIZE;
219 - static constexpr int WARP_NTILE = Ntile / WARP_CNT;
220 - static constexpr int WARP_NITER = WARP_NTILE / 8; // hmma16816
221 - static_assert(WARP_NTILE == 32 or WARP_NTILE == 64,
222 - "now only support WARP_NTILE = 32 or 64!");
223 -
224 - __device__ ComputeTile_W8A16_PerC_MtilexNtilex32_multistage_SM8x_SplitK(
225 - const SM8x_GEMM_W8A16_Splitk_Params<FType, QType>& k_params,
226 - const uint32_t& A_smem_addr, const uint32_t& BQ_smem_addr,
227 - const uint32_t& A_stage_stride, const uint32_t& BQ_stage_stride)
228 - : params(k_params),
229 - A_smem_base_addr(A_smem_addr),
230 - BQ_smem_base_addr(BQ_smem_addr),
231 - A_smem_stage_stride(A_stage_stride),
232 - BQ_smem_stage_stride(BQ_stage_stride) {
233 - warp_id = threadIdx.x / WARP_SIZE;
234 - lane_id = threadIdx.x % WARP_SIZE;
235 -
236 - load_a_base_offset[0] =
237 - (lane_id % 16) * 32 +
238 - ((lane_id / 16) ^ (lane_id % 4) ^ ((lane_id / 4) % 2)) * 8;
239 - load_a_base_offset[1] =
240 - (lane_id % 16) * 32 +
241 - ((lane_id / 16 + 2) ^ (lane_id % 4) ^ ((lane_id / 4) % 2)) * 8;
242 -
243 - load_b_base_offset[0] =
244 - (lane_id / 4 + warp_id * (WARP_NTILE / 4)) * 32 * 4 +
245 - (lane_id % 4) * 16 + ((lane_id / 4) % 2) * 16 * 4;
246 - load_b_base_offset[1] =
247 - (lane_id / 4 + warp_id * (WARP_NTILE / 4)) * 32 * 4 +
248 - (lane_id % 4) * 16 + (((lane_id / 4) % 2) ^ 1) * 16 * 4;
249 -
250 - sts_c_base_offset = warp_id * Mtile * WARP_NTILE +
251 - (lane_id / 4) * WARP_NTILE + (lane_id % 4) * 2;
252 -
253 - if (EnableFuse) {
254 - this_block_C_base_ptr =
255 - params.C_ptr + blockIdx.x * Mtile * params.N + blockIdx.y * Ntile;
256 - } else {
257 - this_block_C_base_ptr =
258 - params.C_split_ptr + blockIdx.z * params.M * params.N +
259 - blockIdx.x * Mtile * params.N + blockIdx.y * Ntile;
260 - }
261 - int store_thds_in_row = WARP_NTILE / 8;
262 - store_c_row_base_idx = lane_id / store_thds_in_row;
263 - store_c_col_idx = warp_id * WARP_NTILE + (lane_id % store_thds_in_row) * 8;
264 - store_c_base_offset = store_c_row_base_idx * params.N + store_c_col_idx;
265 -
266 - #pragma unroll
267 - for (int i = 0; i < Mtile / 16; ++i) {
268 - #pragma unroll
269 - for (int j = 0; j < WARP_NITER; ++j) {
270 - #pragma unroll
271 - for (int k = 0; k < 4; ++k) {
272 - C_frag[i][j][k] = 0.f;
273 - }
274 - }
275 - }
276 - params_n_idx =
277 - blockIdx.y * Ntile + warp_id * WARP_NTILE + (lane_id / 4) * 4;
278 - }
279 -
280 - __device__ void lds(const int& smem_stage_idx, const int& reg_buf_idx,
281 - const int& k_phase_idx) {
282 - uint32_t A_smem_addr =
283 - A_smem_base_addr + A_smem_stage_stride * smem_stage_idx;
284 - uint32_t B_smem_addr =
285 - BQ_smem_base_addr + BQ_smem_stage_stride * smem_stage_idx;
286 -
287 - #pragma unroll
288 - for (int i = 0; i < Mtile / 16; ++i) {
289 - ldsm_4(A_frag[reg_buf_idx][i][0], A_frag[reg_buf_idx][i][1],
290 - A_frag[reg_buf_idx][i][2], A_frag[reg_buf_idx][i][3],
291 - A_smem_addr + (load_a_base_offset[k_phase_idx] + i * 16 * 32) *
292 - sizeof(FType));
293 - }
294 - #pragma unroll
295 - for (int i = 0; i < WARP_NTILE / 32; ++i) {
296 - lds128(BQ_frag[reg_buf_idx][4 * i + 0], BQ_frag[reg_buf_idx][4 * i + 1],
297 - BQ_frag[reg_buf_idx][4 * i + 2], BQ_frag[reg_buf_idx][4 * i + 3],
298 - B_smem_addr + (load_b_base_offset[k_phase_idx] + i * 32 * 32) *
299 - sizeof(uint8_t));
300 - }
301 -
302 - // dequant B
303 - #pragma unroll
304 - for (int i = 0; i < WARP_NITER / 2; ++i) {
305 - cvt_8bx4_to_16bx4_bias128(BQ_frag[reg_buf_idx][2 * i],
306 - BF_frag[reg_buf_idx][2 * i]);
307 - if (has_zp) {
308 - BF_frag[reg_buf_idx][2 * i][0] =
309 - __hsub2(BF_frag[reg_buf_idx][2 * i][0], num2num2(B_zero[i].x));
310 - BF_frag[reg_buf_idx][2 * i][1] =
311 - __hsub2(BF_frag[reg_buf_idx][2 * i][1], num2num2(B_zero[i].x));
312 - }
313 -
314 - BF_frag[reg_buf_idx][2 * i][0] =
315 - __hmul2(BF_frag[reg_buf_idx][2 * i][0], num2num2(B_scale[i].x));
316 - BF_frag[reg_buf_idx][2 * i][1] =
317 - __hmul2(BF_frag[reg_buf_idx][2 * i][1], num2num2(B_scale[i].x));
318 -
319 - cvt_8bx4_to_16bx4_bias128(BQ_frag[reg_buf_idx][2 * i + 1],
320 - BF_frag[reg_buf_idx][2 * i + 1]);
321 - if (has_zp) {
322 - BF_frag[reg_buf_idx][2 * i + 1][0] =
323 - __hsub2(BF_frag[reg_buf_idx][2 * i + 1][0], num2num2(B_zero[i].y));
324 - BF_frag[reg_buf_idx][2 * i + 1][1] =
325 - __hsub2(BF_frag[reg_buf_idx][2 * i + 1][1], num2num2(B_zero[i].y));
326 - }
327 -
328 - BF_frag[reg_buf_idx][2 * i + 1][0] =
329 - __hmul2(BF_frag[reg_buf_idx][2 * i + 1][0], num2num2(B_scale[i].y));
330 - BF_frag[reg_buf_idx][2 * i + 1][1] =
331 - __hmul2(BF_frag[reg_buf_idx][2 * i + 1][1], num2num2(B_scale[i].y));
332 - }
333 - }
334 -
335 - __device__ void ldg_params() {
336 - const int N_padded = (params.N + 31) / 32 * 32;
337 - // load B scale and zero_point
338 - #pragma unroll
339 - for (int i = 0; i < WARP_NTILE / 32; ++i) {
340 - ldg64_ca(B_scale[2 * i + 0], B_scale[2 * i + 1],
341 - params.B_scale_ptr + params_n_idx + i * 32,
342 - (params_n_idx + i * 32) < N_padded);
343 - if (has_zp) {
344 - ldg64_ca(B_zero[2 * i + 0], B_zero[2 * i + 1],
345 - params.B_zero_ptr + params_n_idx + i * 32,
346 - (params_n_idx + i * 32) < N_padded);
347 - }
348 - }
349 - }
350 -
351 - __device__ void mma(const int& reg_buf_idx) {
352 - #pragma unroll
353 - for (int m_idx = 0; m_idx < Mtile / 16; ++m_idx) {
354 - #pragma unroll
355 - for (int n_idx = 0; n_idx < WARP_NITER; ++n_idx) {
356 - hmma16816_f32<FType>(
357 - C_frag[m_idx][n_idx], A_frag[reg_buf_idx][m_idx],
358 - reinterpret_cast<uint32_t (&)[2]>(BF_frag[reg_buf_idx][n_idx]));
359 - }
360 - }
361 - }
362 -
363 - __device__ void fused_splitk_reduce() {
364 - // need splitk-reduce if enable splitk
365 - if (gridDim.z > 1) {
366 - auto blk_red_idx = blockIdx.x * gridDim.y + blockIdx.y;
367 - // Wait for all previous blocks in the splitk direction to accumulate the
368 - // results into C_tmp
369 - if (threadIdx.x == 0) {
370 - uint32_t* red_count_ptr = params.red_count_ptr + blk_red_idx;
371 - uint32_t count;
372 - do {
373 - // make sure the ld.cg inside the do-wile loop
374 - __threadfence_block();
375 - asm volatile("ld.global.cg.b32 %0, [%1];"
376 - : "=r"(count)
377 - : "l"(red_count_ptr));
378 - } while (count != blockIdx.z);
379 - }
380 - __syncthreads();
381 -
382 - auto C_tmp_base_offset = blk_red_idx * Mtile * Ntile + threadIdx.x * 4;
383 - if (blockIdx.z != 0) {
384 - // expecting that temporary register here reuses the previous A&B frag
385 - // register
386 - float temp_frag[Mtile / 16][WARP_NITER][4];
387 - #pragma unroll
388 - for (int m_idx = 0; m_idx < Mtile / 16; ++m_idx) {
389 - #pragma unroll
390 - for (int n_idx = 0; n_idx < WARP_NITER; ++n_idx) {
391 - int offset =
392 - C_tmp_base_offset + (m_idx * WARP_NITER + n_idx) * BLOCK * 4;
393 - *reinterpret_cast<int4*>(temp_frag[m_idx][n_idx]) =
394 - *reinterpret_cast<int4*>(params.C_tmp_ptr + offset);
395 - }
396 - }
397 - #pragma unroll
398 - for (int m_idx = 0; m_idx < Mtile / 16; ++m_idx) {
399 - #pragma unroll
400 - for (int n_idx = 0; n_idx < WARP_NITER; ++n_idx) {
401 - #pragma unroll
402 - for (int idx = 0; idx < 4; ++idx) {
403 - C_frag[m_idx][n_idx][idx] += temp_frag[m_idx][n_idx][idx];
404 - }
405 - }
406 - }
407 - }
408 -
409 - // first splitk - 1 blocks need to write partial results into C_tmp
410 - if (blockIdx.z != gridDim.z - 1) {
411 - #pragma unroll
412 - for (int m_idx = 0; m_idx < Mtile / 16; ++m_idx) {
413 - #pragma unroll
414 - for (int n_idx = 0; n_idx < WARP_NITER; ++n_idx) {
415 - int offset =
416 - C_tmp_base_offset + (m_idx * WARP_NITER + n_idx) * BLOCK * 4;
417 - asm volatile(
418 - "{st.global.cg.v4.b32 [%0], {%1, %2, %3, %4};}\n"
419 - :
420 - : "l"(params.C_tmp_ptr + offset), "f"(C_frag[m_idx][n_idx][0]),
421 - "f"(C_frag[m_idx][n_idx][1]), "f"(C_frag[m_idx][n_idx][2]),
422 - "f"(C_frag[m_idx][n_idx][3]));
423 - }
424 - }
425 - __threadfence();
426 - __syncthreads();
427 - if (threadIdx.x == 0) {
428 - uint32_t* red_count_ptr = params.red_count_ptr + blk_red_idx;
429 - atomicInc(red_count_ptr, gridDim.z);
430 - }
431 - }
432 - }
433 - }
434 -
435 - __device__ void stg(char* smem) {
436 - if (EnableFuse) {
437 - if (blockIdx.z != gridDim.z - 1) return;
438 - }
439 - uint32_t* C_sts_ptr =
440 - reinterpret_cast<uint32_t*>(smem + sts_c_base_offset * sizeof(FType));
441 - // C_tile sts
442 - #pragma unroll
443 - for (int m_idx = 0; m_idx < Mtile / 16; ++m_idx) {
444 - #pragma unroll
445 - for (int n_idx = 0; n_idx < WARP_NITER; ++n_idx) {
446 - #pragma unroll
447 - for (int k_idx = 0; k_idx < 2; ++k_idx) {
448 - FType low16 = MarlinScalarType2<FType>::float2num(
449 - C_frag[m_idx][n_idx][k_idx * 2]);
450 - FType high16 = MarlinScalarType2<FType>::float2num(
451 - C_frag[m_idx][n_idx][k_idx * 2 + 1]);
452 - uint32_t tmp = (reinterpret_cast<uint32_t&>(low16) & 0xffff) |
453 - (reinterpret_cast<uint32_t&>(high16) << 16);
454 - int sts_offset =
455 - m_idx * 16 * (WARP_NTILE / 2) +
456 - (((lane_id / (32 / WARP_NITER)) + n_idx) % WARP_NITER) * (8 / 2) +
457 - k_idx * 8 * (WARP_NTILE / 2);
458 - C_sts_ptr[sts_offset] = tmp;
459 - }
460 - }
461 - }
462 -
463 - __syncthreads();
464 -
465 - FType* C_base_ptr = this_block_C_base_ptr + store_c_base_offset;
466 - // C_tile lds and stg
467 - auto m_base_idx = store_c_row_base_idx + blockIdx.x * Mtile;
468 - bool n_guard = (store_c_col_idx + blockIdx.y * Ntile) < params.N;
469 - if (WARP_NTILE == 32) {
470 - int lds_c_base_offset = warp_id * Mtile * WARP_NTILE +
471 - (lane_id / 4) * WARP_NTILE +
472 - ((lane_id % 4 + lane_id / 8) % 4) * 8;
473 - uint4* C_lds_ptr =
474 - reinterpret_cast<uint4*>(smem + lds_c_base_offset * sizeof(FType));
475 - #pragma unroll
476 - for (int i = 0; i < (Mtile / 16) * (WARP_NITER / 2); ++i) {
477 - uint4 stg_reg = C_lds_ptr[i * 8 * 4];
478 - stg128(stg_reg.x, stg_reg.y, stg_reg.z, stg_reg.w,
479 - C_base_ptr + i * 8 * params.N,
480 - (m_base_idx + i * 8) < params.M && n_guard);
481 - }
482 - } else if (WARP_NTILE == 64) {
483 - int lds_c_base_offset =
484 - warp_id * Mtile * WARP_NTILE + (lane_id / 8) * WARP_NTILE;
485 - #pragma unroll
486 - for (int i = 0; i < (Mtile / 16) * (WARP_NITER / 2); ++i) {
487 - int lds_c_offset = lds_c_base_offset + i * 4 * WARP_NTILE +
488 - ((lane_id % 8 + lane_id / 8 + (i % 2) * 4) % 8) * 8;
489 - uint4 stg_reg =
490 - *reinterpret_cast<uint4*>(smem + lds_c_offset * sizeof(FType));
491 - stg128(stg_reg.x, stg_reg.y, stg_reg.z, stg_reg.w,
492 - C_base_ptr + i * 4 * params.N,
493 - (m_base_idx + i * 4) < params.M && n_guard);
494 - }
495 - }
496 - }
497 -
498 - const SM8x_GEMM_W8A16_Splitk_Params<FType, QType>& params;
499 -
500 - int load_a_base_offset[2];
501 - int load_b_base_offset[2];
502 - int sts_c_base_offset;
503 -
504 - int store_c_base_offset;
505 -
506 - int store_c_row_base_idx, store_c_col_idx;
507 - FType* this_block_C_base_ptr = nullptr;
508 -
509 - int params_n_idx;
510 - const uint32_t A_smem_base_addr, BQ_smem_base_addr;
511 - const uint32_t A_smem_stage_stride, BQ_smem_stage_stride;
512 -
513 - int lane_id;
514 - int warp_id;
515 - // first 2 denotes double buffer, second dim denotes M direction
516 - uint32_t A_frag[2][Mtile / 16][4];
517 -
518 - typename HalfType<FType>::T2 B_scale[WARP_NITER / 2];
519 - typename HalfType<FType>::T2 B_zero[WARP_NITER / 2];
520 - uint32_t BQ_frag[2][WARP_NITER];
521 - // first 2 denotes double buffer, second dim denotes N direction, last 2
522 - // denotes K direction
523 - typename HalfType<FType>::T2 BF_frag[2][WARP_NITER][2];
524 - // first dim denotes M direction, second dim denotes N direction
525 - float C_frag[Mtile / 16][WARP_NITER][4];
526 -};
527 -
528 -/*
529 - * @brief W8A16 Perchannel Quantization GEMM,
530 - * requires N % 8 == 0, K % 16 == 0
531 - * accumulator precision: FP32
532 - * @tparam FType: DataType for A, B_scale, B_zero, and C, supports half or
533 - * nv_bfloat16
534 - * @tparam QType: DataType for B, support uint8(bias128)
535 - * @tparam Mtile: M-dimensional size of the gemm block tile, supports 16, 32,
536 - * 48 or 64
537 - * @tparam Ntile: N-dimensional size of the gemm block tile, supports 128 or
538 - * 256
539 - * @tparam NStage: Num of stages for async copy
540 - * @tparam BLOCK: BLOCK size
541 - * @tparam EnableFuse: If true, use fused splitk-reduce, otherwise use
542 - * non-fused splitk-reduce
543 - * @tparam has_zp: whether to use zero_point
544 - *
545 - * @fparam params struct consists of following parameters:
546 - * @param A_ptr: Matrix A value ptr, A = (M, K)
547 - * @param B_ptr: Matrix B value ptr, B = (N32_align, K) (N32K16 special
548 - * format), N32_align = (N + 32 - 1) / 32 * 32
549 - * @param B_scale_ptr: B_scale value ptr, B_scale = (N32_align,) (N32K16
550 - * special format)
551 - * @param B_zero_ptr: B_zero value ptr, B_zero = (N32_align,) (N32K16
552 - * special format)
553 - * @param C_ptr: Matrix C value ptr, C = (M, N)
554 - * @param M: dimnesion m
555 - * @param N: dimnesion n
556 - * @param K: dimnesion k
557 - * @param SplitK: split size along K-dimension
558 - * @param C_split_ptr: Matrix C_split value ptr, used only in non-fused
559 - * splitk-reduce
560 - * @param C_tmp_ptr: Matrix C_tmp value ptr, used only in fused
561 - * splitk-reduce
562 - * @param red_count_ptr: 1-D red_count value ptr, used only in fused
563 - * splitk-reduce
564 - */
565 -template <typename FType, typename QType, int Mtile, int Ntile, int NStage,
566 - int BLOCK, bool EnableFuse, bool has_zp>
567 -__global__ void __launch_bounds__(BLOCK)
568 - ampere_hgemm_W8A16_perc_f16_f16_MtilexNtilex32_hmma16816_multistage_AN_BTN32K16_CN_splitk_kernel(
569 - const SM8x_GEMM_W8A16_Splitk_Params<FType, QType> params) {
570 - // A smem size = 64 * 32 * 2B/elem * 4(stage) = 16KB
571 - // B smem size = 128 * 32 * 1B/elem * 4(stage) = 16KB
572 - constexpr int smem_size_one_stage = Mtile * 32 * 2 + Ntile * 32;
573 - __shared__ char smem[NStage * smem_size_one_stage];
574 - char* A_smem = smem;
575 - char* BQ_smem = smem + Mtile * 32 * 2 * NStage;
576 -
577 - uint32_t A_smem_addr = smem_u32addr(A_smem);
578 - uint32_t BQ_smem_addr = smem_u32addr(BQ_smem);
579 - uint32_t A_smem_stage_stride = Mtile * 32 * 2;
580 - uint32_t BQ_smem_stage_stride = Ntile * 32;
581 -
582 - // initialize the data move process from GM to SMEM for this block
583 - GmemTile_W8A16_PerC_MtilexNtilex32_multistage_SM8x_SplitK<
584 - FType, QType, Mtile, Ntile, NStage, BLOCK>
585 - gmem_tile(params, A_smem_addr, BQ_smem_addr, A_smem_stage_stride,
586 - BQ_smem_stage_stride);
587 -
588 - int sts_stage_idx = 0;
589 - int lds_stage_idx = 0;
590 -
591 - auto tb_k_slice = blockIdx.z * params.SplitK + params.SplitK <= params.K
592 - ? params.SplitK
593 - : params.K - blockIdx.z * params.SplitK;
594 - int k_tiles = (tb_k_slice + 31) / 32;
595 - int first_k_tile = tb_k_slice - (k_tiles - 1) * 32;
596 -
597 - // load first three tiles to shared memory
598 - gmem_tile.ldgsts_first_ktiles(first_k_tile, k_tiles);
599 - sts_stage_idx += (NStage - 2);
600 - ComputeTile_W8A16_PerC_MtilexNtilex32_multistage_SM8x_SplitK<
601 - FType, QType, Mtile, Ntile, BLOCK, EnableFuse, has_zp>
602 - compute_tile(params, A_smem_addr, BQ_smem_addr, A_smem_stage_stride,
603 - BQ_smem_stage_stride);
604 - compute_tile.ldg_params();
605 - cp_asyc_wait_group<NStage - 2>();
606 - __syncthreads();
607 -
608 - compute_tile.lds(lds_stage_idx, 0, 0);
609 - int reg_buf_idx = 1;
610 -
611 - // main loop
612 - for (; k_tiles > NStage - 1; --k_tiles) {
613 - // load next A&B tile
614 - sts_stage_idx = sts_stage_idx < NStage - 1 ? sts_stage_idx + 1 : 0;
615 - gmem_tile.ldgsts(sts_stage_idx);
616 -
617 - #pragma unroll
618 - for (int k_phase_idx = 0; k_phase_idx < 2; k_phase_idx++) {
619 - // dequantize next B tile
620 - if (k_phase_idx == 1) {
621 - cp_asyc_wait_group<NStage - 2>();
622 - __syncthreads();
623 - lds_stage_idx = lds_stage_idx < NStage - 1 ? lds_stage_idx + 1 : 0;
624 - }
625 -
626 - compute_tile.lds(lds_stage_idx, reg_buf_idx, (k_phase_idx + 1) % 2);
627 -
628 - compute_tile.mma(reg_buf_idx ^ 1);
629 - reg_buf_idx ^= 1;
630 - }
631 - }
632 -
633 - // last NStage-1 tiles
634 - for (; k_tiles > 0; --k_tiles) {
635 - cp_async_commit_group();
636 - #pragma unroll
637 - for (int k_phase_idx = 0; k_phase_idx < 2; k_phase_idx++) {
638 - // dequantize next B tile
639 - if (k_phase_idx == 1) {
640 - cp_asyc_wait_group<NStage - 2>();
641 - __syncthreads();
642 - lds_stage_idx = lds_stage_idx < NStage - 1 ? lds_stage_idx + 1 : 0;
643 - }
644 -
645 - compute_tile.lds(lds_stage_idx, reg_buf_idx, (k_phase_idx + 1) % 2);
646 -
647 - compute_tile.mma(reg_buf_idx ^ 1);
648 - reg_buf_idx ^= 1;
649 - }
650 - }
651 -
652 - if (EnableFuse) {
653 - compute_tile.fused_splitk_reduce();
654 - }
655 - compute_tile.stg(smem);
656 -}
657 -
658 - #define __CALL_IF(MTILE, NTILE, NUM_THREADS, ENABLE_FUSE, HAS_ZP) \
659 - else if (Mtile == MTILE && Ntile == NTILE && BLOCK == NUM_THREADS && \
660 - enable_fuse == ENABLE_FUSE && has_zp == HAS_ZP) { \
661 - ampere_hgemm_W8A16_perc_f16_f16_MtilexNtilex32_hmma16816_multistage_AN_BTN32K16_CN_splitk_kernel< \
662 - FType, QType, MTILE, NTILE, 4, NUM_THREADS, ENABLE_FUSE, HAS_ZP> \
663 - <<<grid, block, 0, stream>>>(params); \
664 - }
665 -
666 -template <typename FType, typename QType>
667 -void ampere_hgemm_W8A16_perc_f16_f16_MtilexNtilex32_mma16816_multistage_AN_BTN32K16_CN_splitk(
668 - const FType* A, const QType* B, const FType* B_scale, const FType* B_zero,
669 - FType* C, const int M, const int N, const int K, void* workspace,
670 - const int sm_version, const BlockTileSplitkParams& fused_gemm_params,
671 - cudaStream_t stream) {
672 - int Mtile = fused_gemm_params.Mtile;
673 - int grid_x = (M + Mtile - 1) / Mtile;
674 - int Ntile = fused_gemm_params.Ntile;
675 - int grid_y = (N + Ntile - 1) / Ntile;
676 - int SplitK = fused_gemm_params.SplitK;
677 - int grid_z = (K + SplitK - 1) / SplitK;
678 -
679 - int BLOCK = (Ntile == 256) ? 256 : 128;
680 -
681 - dim3 grid(grid_x, grid_y, grid_z);
682 - dim3 block(BLOCK);
683 -
684 - bool enable_fuse = fused_gemm_params.EnableFuse;
685 - bool has_zp = B_zero != nullptr;
686 - if (enable_fuse) {
687 - float* C_tmp = reinterpret_cast<float*>(workspace);
688 - uint32_t* red_count = reinterpret_cast<uint32_t*>(
689 - (char*)workspace + grid_x * Mtile * grid_y * Ntile * sizeof(float));
690 - CHECK_CUDA(cudaMemsetAsync(red_count, 0, grid_x * grid_y * sizeof(uint32_t),
691 - stream));
692 - SM8x_GEMM_W8A16_Splitk_Params<FType, QType> params{
693 - A, B, B_scale, B_zero, C, M, N,
694 - K, SplitK, 0, -1, nullptr, C_tmp, red_count};
695 -
696 - if (false) {
697 - }
698 - // Select the template parameters for kernel launch
699 - // according to the above settings. Tuning is not supported.
700 - __CALL_IF(16, 256, 256, true, false)
701 - __CALL_IF(32, 256, 256, true, false)
702 - __CALL_IF(48, 256, 256, true, false)
703 - __CALL_IF(64, 128, 128, true, false)
704 - __CALL_IF(64, 256, 256, true, false)
705 - __CALL_IF(16, 256, 256, true, true)
706 - __CALL_IF(32, 256, 256, true, true)
707 - __CALL_IF(48, 256, 256, true, true)
708 - __CALL_IF(64, 128, 128, true, true)
709 - __CALL_IF(64, 256, 256, true, true)
710 - } else {
711 - FType* C_split = reinterpret_cast<FType*>(workspace);
712 - SM8x_GEMM_W8A16_Splitk_Params<FType, QType> params{
713 - A, B, B_scale, B_zero, C, M, N,
714 - K, SplitK, 0, -1, C_split, nullptr, nullptr};
715 -
716 - if (false) {
717 - }
718 - // Select the template parameters for kernel launch
719 - // according to the above settings. Tuning is not supported.
720 - __CALL_IF(16, 256, 256, false, false)
721 - __CALL_IF(32, 256, 256, false, false)
722 - __CALL_IF(48, 256, 256, false, false)
723 - __CALL_IF(64, 128, 128, false, false)
724 - __CALL_IF(64, 256, 256, false, false)
725 - __CALL_IF(16, 256, 256, false, true)
726 - __CALL_IF(32, 256, 256, false, true)
727 - __CALL_IF(48, 256, 256, false, true)
728 - __CALL_IF(64, 128, 128, false, true)
729 - __CALL_IF(64, 256, 256, false, true)
730 -
731 - // SplitK reduce
732 - f16_gemm_splitk_reduce(C_split, C, M, N, grid_z, stream);
733 - }
734 -}
735 -
736 -size_t allspark_qgemm_w8a16_perc_n32k16_ampere_workspace_size(
737 - int m, int n, int k, int sm_count,
738 - BlockTileSplitkParams& fused_gemm_params) {
739 - // Determine the block tile and splitk strategy
740 - int m16_times = (m + 16 - 1) / 16;
741 - int Mtile = m16_times <= 4 ? m16_times * 16 : 64;
742 - int grid_x = (m + Mtile - 1) / Mtile;
743 - int Ntile =
744 - (float(grid_x * ((n + 127) / 128)) / sm_count > 10) || (Mtile < 64) ? 256
745 - : 128;
746 - int grid_y = (n + Ntile - 1) / Ntile;
747 - int grid_z;
748 -
749 - // split-k
750 - const float SPLIT_THRESHOLD = 0.8;
751 - int n_slice;
752 - for (n_slice = 1; n_slice < k / 256; ++n_slice) {
753 - int n_block = grid_x * grid_y * n_slice;
754 - if (n_block >= sm_count * SPLIT_THRESHOLD &&
755 - (n_block % sm_count == 0 || n_block % sm_count >= sm_count * 0.5)) {
756 - break;
757 - }
758 - }
759 -
760 - int k_slice =
761 - (k / n_slice) % 32 == 0 ? k / n_slice : k / n_slice / 32 * 32 + 32;
762 - grid_z = (k + k_slice - 1) / k_slice;
763 - bool enable_fuse = float(grid_x * grid_y) / sm_count >= 0.5 ? 1 : 0;
764 -
765 - size_t ws_size;
766 - if (enable_fuse) {
767 - ws_size = grid_x * Mtile * grid_y * Ntile * sizeof(float) // For C_tmp
768 - + grid_x * grid_y * sizeof(uint32_t); // For red_count
769 - } else {
770 - ws_size = grid_z * m * n * sizeof(__half);
771 - }
772 -
773 - fused_gemm_params.Mtile = Mtile;
774 - fused_gemm_params.Ntile = Ntile;
775 - fused_gemm_params.SplitK = k_slice;
776 - fused_gemm_params.EnableFuse = enable_fuse;
777 - return ws_size;
778 -}
779 -
780 -// restore from N32K16 order to original N-major order
781 -// K % 16 == 0, N % 8 == 0
782 -// each block process 64(k) * 32(n) result elements
783 -template <typename FT, typename QT>
784 -__global__ void restore_N32_K16_dequantize_rhs_w8a16_perc_kernel(
785 - const QT* qdata, const FT* scales, const FT* zeros, FT* fdata,
786 - const int N_32align, const int N, const int K) {
787 - __shared__ FT smem[64 * 32];
788 - auto warp_id = threadIdx.x / 32;
789 - auto lane_id = threadIdx.x % 32;
790 - const auto src_row_idx = blockIdx.x * 8 + lane_id / 4;
791 - const int src_col_idx =
792 - blockIdx.y * 64 * 4 + warp_id * 16 * 4 + (lane_id % 4) * 16;
793 - const int src_offset = src_row_idx * K * 4 + src_col_idx;
794 - auto params_nidx = blockIdx.x * 32 + (lane_id / 4) * 4;
795 -
796 - QT qval_reg[16];
797 - const QT* pdata = qdata + src_offset;
798 - if (src_col_idx < (K * 4)) {
799 - *(reinterpret_cast<uint4*>(qval_reg)) =
800 - *(reinterpret_cast<const uint4*>(qdata + src_offset));
801 - }
802 - FT scale_reg[4];
803 - *(reinterpret_cast<uint2*>(scale_reg)) =
804 - *(reinterpret_cast<const uint2*>(scales + params_nidx));
805 - FT zero_reg[4];
806 - if (zeros != nullptr) {
807 - *(reinterpret_cast<uint2*>(zero_reg)) =
808 - *(reinterpret_cast<const uint2*>(zeros + params_nidx));
809 - }
810 - FT fval_reg[16];
811 -
812 - const int sts_base_offset =
813 - (warp_id * 16 + (lane_id % 4) * 2) * 32 + lane_id / 4;
814 - #pragma unroll
815 - for (int ni = 0; ni < 4; ++ni) {
816 - cvt_8bx4_to_16bx4_bias128(
817 - *reinterpret_cast<uint32_t*>(&qval_reg[ni * 4]),
818 - reinterpret_cast<typename HalfType<FT>::T2*>(&(fval_reg[ni * 4])));
819 - #pragma unroll
820 - for (int ki = 0; ki < 4; ++ki) {
821 - if (zeros != nullptr) {
822 - fval_reg[ni * 4 + ki] = __hsub(fval_reg[ni * 4 + ki], zero_reg[ni]);
823 - }
824 - fval_reg[ni * 4 + ki] = __hmul(fval_reg[ni * 4 + ki], scale_reg[ni]);
825 - int sts_offset = sts_base_offset + ((ki / 2) * 8 + (ki % 2)) * 32 +
826 - ((ni + lane_id % 4) % 4) * 8;
827 - smem[sts_offset] = fval_reg[ni * 4 + ki];
828 - }
829 - }
830 - __syncthreads();
831 -
832 - const int lds_base_offset =
833 - (threadIdx.x / 4) * 32 + ((threadIdx.x % 4 + threadIdx.x / 8) % 4) * 8;
834 - #pragma unroll
835 - for (int i = 0; i < 2; ++i) {
836 - *reinterpret_cast<uint4*>(fval_reg + i * 8) =
837 - *reinterpret_cast<uint4*>(smem + lds_base_offset + i * 32 * 32);
838 - }
839 -
840 - const auto dst_row_base_kidx = blockIdx.y * 64 + threadIdx.x / 4;
841 - const auto dst_col_nidx = blockIdx.x * 32 + (threadIdx.x % 4) * 8;
842 - #pragma unroll
843 - for (int i = 0; i < 2; ++i) {
844 - int dst_row_kidx = dst_row_base_kidx + i * 32;
845 - int dst_offset = dst_row_kidx * N + dst_col_nidx;
846 - if (dst_row_kidx < K && dst_col_nidx < N) {
847 - *reinterpret_cast<uint4*>(fdata + dst_offset) =
848 - *reinterpret_cast<uint4*>(fval_reg + i * 8);
849 - }
850 - }
851 -}
852 -
853 -template <typename FT, typename QT>
854 -void restore_N32_K16_dequantize_rhs_w8a16(const QT* qdata, const FT* scales,
855 - const FT* zeros, FT* fdata,
856 - const int N_32align, const int N,
857 - const int K, const int GroupSize,
858 - cudaStream_t stream) {
859 - STD_TORCH_CHECK(N % 8 == 0 && K % 16 == 0 && N_32align % 32 == 0,
860 - "Unsupported shape");
861 - if (GroupSize == -1) {
862 - const int BLOCK = 128;
863 - dim3 grid(N_32align / 32, ((K / 16) + 3) / 4);
864 - restore_N32_K16_dequantize_rhs_w8a16_perc_kernel<FT, QT>
865 - <<<grid, BLOCK, 0, stream>>>(qdata, scales, zeros, fdata, N_32align, N,
866 - K);
867 - }
868 - // TODO: Support SubChannel
869 - else {
870 - STD_TORCH_CHECK(false, "Now only support PerChannel");
871 - }
872 -}
873 -
874 -template <typename FT, typename QT>
875 -void w8a16_gemm_dq_cublas(const FT* in, const QT* rhs_qdata_ptr,
876 - const FT* rhs_scales_ptr, const FT* rhs_zeros_ptr,
877 - FT* out, void* workspace, const int M,
878 - const int N_32align, const int N, const int K,
879 - const int group_size, cudaStream_t stream,
880 - cublasHandle_t handle) {
881 - static_assert(
882 - std::is_same<FT, half>::value || std::is_same<FT, nv_bfloat16>::value,
883 - "only float16 and bfloat16 is supported");
884 - // Dequant
885 - FT* rhs_fdata_ptr = static_cast<FT*>(workspace);
886 - restore_N32_K16_dequantize_rhs_w8a16(rhs_qdata_ptr, rhs_scales_ptr,
887 - rhs_zeros_ptr, rhs_fdata_ptr, N_32align,
888 - N, K, group_size, stream);
889 - // cuBLAS GEMM
890 - int lda = K;
891 - int ldb = N;
892 - int ldc = N;
893 - const float alpha = 1.0f;
894 - const float beta = 0.0f;
895 - cudaDataType_t cuda_type;
896 - if (std::is_same<FT, __half>::value) {
897 - cuda_type = CUDA_R_16F;
898 - } else {
899 - cuda_type = CUDA_R_16BF;
900 - }
901 - CHECK_CUBLAS(cublasGemmEx(handle, CUBLAS_OP_N, CUBLAS_OP_N, N, M, K, &alpha,
902 - rhs_fdata_ptr, cuda_type, ldb, in, cuda_type, lda,
903 - &beta, out, cuda_type, ldc, CUDA_R_32F,
904 - CUBLAS_GEMM_DEFAULT_TENSOR_OP));
905 -}
906 -
907 -template <typename FType, typename QType>
908 -void allspark_qgemm_w8a16_perc_ampere(
909 - const FType* A, const QType* B, const FType* B_scale, const FType* B_zero,
910 - FType* C, const int M, const int N_32align, const int N, const int K,
911 - void* workspace, const BlockTileSplitkParams& fused_gemm_params,
912 - const int group_size, int CUBLAS_M_THRESHOLD, const int sm_version,
913 - cudaStream_t stream, cublasHandle_t handle) {
914 - if (M > CUBLAS_M_THRESHOLD) {
915 - w8a16_gemm_dq_cublas<FType, QType>(A, B, B_scale, B_zero, C, workspace, M,
916 - N_32align, N, K, group_size, stream,
917 - handle);
918 - } else {
919 - ampere_hgemm_W8A16_perc_f16_f16_MtilexNtilex32_mma16816_multistage_AN_BTN32K16_CN_splitk<
920 - FType, QType>(A, B, B_scale, B_zero, C, M, N, K, workspace, sm_version,
921 - fused_gemm_params, stream);
922 - }
923 -}
924 -
925 -} // namespace allspark
926 -
927 -torch::stable::Tensor allspark_w8a16_gemm(
928 - torch::stable::Tensor const& a, torch::stable::Tensor const& b_qweight,
929 - torch::stable::Tensor const& b_scales,
930 - std::optional<torch::stable::Tensor> const& b_qzeros, int64_t n,
931 - int64_t group_size, int64_t sm_count, int64_t sm_version,
932 - int64_t CUBLAS_M_THRESHOLD, bool has_zp, bool n32k16_reorder) {
933 - // Verify device and strides
934 - STD_TORCH_CHECK(a.device().is_cuda(), "A is not on GPU");
935 - STD_TORCH_CHECK(a.is_contiguous(), "A is not contiguous");
936 -
937 - STD_TORCH_CHECK(b_qweight.device().is_cuda(), "b_qweight is not on GPU");
938 - STD_TORCH_CHECK(b_qweight.is_contiguous(), "b_qweight is not contiguous");
939 -
940 - STD_TORCH_CHECK(b_scales.device().is_cuda(), "b_scales is not on GPU");
941 - STD_TORCH_CHECK(b_scales.is_contiguous(), "b_scales is not contiguous");
942 -
943 - if (has_zp) {
944 - STD_TORCH_CHECK(b_qzeros.value().device().is_cuda(),
945 - "b_qzeros is not on GPU");
946 - STD_TORCH_CHECK(b_qzeros.value().is_contiguous(),
947 - "b_qzeros is not contiguous");
948 - }
949 -
950 - int m = a.size(0);
951 - int n_32align = (n + 32 - 1) / 32 * 32;
952 - int k = a.size(1);
953 -
954 - // Verify shape
955 - STD_TORCH_CHECK(b_qweight.size(0) == n_32align,
956 - "Shape mismatch: b_qweight.size(0) = ", b_qweight.size(0),
957 - ", n_32align = ", n_32align);
958 - STD_TORCH_CHECK(b_qweight.size(1) == k,
959 - "Shape mismatch: b_qweight.size(1) = ", b_qweight.size(1),
960 - ", k = ", k);
961 -
962 - STD_TORCH_CHECK(group_size == -1, "Currently only supports group_size = -1");
963 -
964 - const torch::stable::accelerator::DeviceGuard device_guard(
965 - a.get_device_index());
966 - const void* a_ptr = reinterpret_cast<const void*>(a.data_ptr());
967 - const uint8_t* b_ptr = reinterpret_cast<const uint8_t*>(b_qweight.data_ptr());
968 - const void* b_scale_ptr = reinterpret_cast<const void*>(b_scales.data_ptr());
969 - const void* b_zero_ptr = nullptr;
970 - if (b_qzeros.has_value()) {
971 - b_zero_ptr = reinterpret_cast<const void*>(b_qzeros.value().data_ptr());
972 - }
973 -
974 - auto c =
975 - torch::stable::empty({m, n}, a.scalar_type(), std::nullopt, a.device());
976 - void* c_ptr = reinterpret_cast<void*>(c.mutable_data_ptr());
977 -
978 - cudaStream_t stream = get_current_cuda_stream();
979 - cublasHandle_t handle = get_current_cuda_blas_handle();
980 -
981 - allspark::BlockTileSplitkParams fused_gemm_params;
982 -
983 - size_t ws_size = 0;
984 - if (m > CUBLAS_M_THRESHOLD) {
985 - ws_size = k * n * 2; // sizeof(f16)==2
986 - } else {
987 - ws_size = allspark::allspark_qgemm_w8a16_perc_n32k16_ampere_workspace_size(
988 - m, n, k, sm_count, fused_gemm_params);
989 - }
990 -
991 - if (as_g_workspace.numel() <
992 - ws_size) { // ws_options: kChar, so numel() is bytes
993 - as_g_workspace = torch::stable::empty({static_cast<int64_t>(ws_size)},
994 - torch::headeronly::ScalarType::Char,
995 - std::nullopt, a.device());
996 - }
997 - void* ws = reinterpret_cast<void*>(as_g_workspace.data_ptr());
998 -
999 - if (a.scalar_type() == torch::headeronly::ScalarType::Half) {
1000 - allspark::allspark_qgemm_w8a16_perc_ampere<__half, uint8_t>(
1001 - reinterpret_cast<const __half*>(a_ptr), b_ptr,
1002 - reinterpret_cast<const __half*>(b_scale_ptr),
1003 - reinterpret_cast<const __half*>(b_zero_ptr),
1004 - reinterpret_cast<__half*>(c_ptr), m, n_32align, n, k, ws,
1005 - fused_gemm_params, group_size, CUBLAS_M_THRESHOLD, sm_version, stream,
1006 - handle);
1007 - } else if (a.scalar_type() == torch::headeronly::ScalarType::BFloat16) {
1008 - allspark::allspark_qgemm_w8a16_perc_ampere<__nv_bfloat16, uint8_t>(
1009 - reinterpret_cast<const __nv_bfloat16*>(a_ptr), b_ptr,
1010 - reinterpret_cast<const __nv_bfloat16*>(b_scale_ptr),
1011 - reinterpret_cast<const __nv_bfloat16*>(b_zero_ptr),
1012 - reinterpret_cast<__nv_bfloat16*>(c_ptr), m, n_32align, n, k, ws,
1013 - fused_gemm_params, group_size, CUBLAS_M_THRESHOLD, sm_version, stream,
1014 - handle);
1015 - }
1016 -
1017 - return c;
1018 -}
1019 -
1020 -#endif
1021 -
1022 -STABLE_TORCH_LIBRARY_IMPL(_C, CUDA, m) {
1023 - m.impl("allspark_w8a16_gemm", TORCH_BOX(&allspark_w8a16_gemm));
1024 -}
csrc/libtorch_stable/quantization/gptq_allspark/allspark_repack.cu deleted
-176
@@ -1,176 +0,0 @@
1 -#include "allspark_utils.cuh"
2 -
3 -#include <torch/csrc/stable/library.h>
4 -#include <torch/csrc/stable/tensor.h>
5 -#include <torch/headeronly/core/ScalarType.h>
6 -
7 -#include "core/registration.h"
8 -#include "libtorch_stable/torch_utils.h"
9 -
10 -namespace allspark {
11 -
12 -// Rearrange B to facilitate Ampere Tensor Core load data
13 -// reorder B from (K, N) to (N_32align / 4, K * 4)
14 -// K % 16 == 0, N % 16 == 0, N_32align % 32 == 0
15 -template <typename FType>
16 -__global__ void __launch_bounds__(128)
17 - rearrange_kn_weight_as_n32k16_order_ldg16_kernel(
18 - const uint8_t* B, const FType* B_scale, const FType* B_zero,
19 - uint8_t* B_result, FType* B_scale_result, FType* B_zero_result,
20 - const int K, const int N, const int N_32align) {
21 - const auto lane_id = threadIdx.x % 32;
22 - const auto warp_id = threadIdx.x / 32;
23 -
24 - if (blockIdx.x != gridDim.x - 1) {
25 - // Load B
26 - // per block process 64(k) * 128(n) B elements
27 - // per warp process 16(k) * 128 B elements
28 - const int src_row_base_idx =
29 - blockIdx.x * 64 + warp_id * 16 + ((lane_id % 8) / 2) * 2;
30 - const int src_col_idx =
31 - blockIdx.y * 128 + (lane_id / 8) * 32 + (lane_id % 2) * 16;
32 - uint8_t B_frag[4][16];
33 -#pragma unroll
34 - for (int i = 0; i < 4; ++i) {
35 - int src_row_idx = src_row_base_idx + (i / 2) * 8 + (i % 2);
36 - int src_offset = src_row_idx * N + src_col_idx;
37 - bool guard = src_row_idx < K && src_col_idx < N;
38 - ldg128_cg_0(*reinterpret_cast<uint32_t*>(B_frag[i]),
39 - *(reinterpret_cast<uint32_t*>(B_frag[i]) + 1),
40 - *(reinterpret_cast<uint32_t*>(B_frag[i]) + 2),
41 - *(reinterpret_cast<uint32_t*>(B_frag[i]) + 3), B + src_offset,
42 - guard);
43 - }
44 -
45 - // reorder B
46 - uint8_t B_reorder_frag[8][8];
47 -#pragma unroll
48 - for (int i = 0; i < 4; ++i) {
49 -#pragma unroll
50 - for (int j = 0; j < 16; ++j) {
51 - int dst_i = j % 8;
52 - int dst_j = i + (j / 8) * 4;
53 - B_reorder_frag[dst_i][dst_j] = B_frag[i][j];
54 - }
55 - }
56 -
57 - // Store B
58 - const auto dst_row_base_idx = blockIdx.y * (128 / 4) + (lane_id / 8) * 8;
59 - const int dst_col_idx =
60 - blockIdx.x * (64 * 4) + warp_id * 64 + (lane_id % 8) * 8;
61 - for (int i = 0; i < 8; ++i) {
62 - int dst_row_idx = dst_row_base_idx + i;
63 - int dst_offset = dst_row_idx * K * 4 + dst_col_idx;
64 - bool guard = (dst_row_base_idx < N_32align / 4) && (dst_col_idx < K * 4);
65 - if (guard) {
66 - *reinterpret_cast<int2*>(B_result + dst_offset) =
67 - *reinterpret_cast<int2*>(B_reorder_frag[i]);
68 - }
69 - }
70 - } else {
71 - // Load B_scale and B_zero
72 - FType b_scale_reg, b_zero_reg;
73 - auto src_offset = blockIdx.y * 128 + threadIdx.x;
74 - ldg16_cg_0(b_scale_reg, B_scale + src_offset, src_offset < N);
75 - if (B_zero != nullptr)
76 - ldg16_cg_0(b_zero_reg, B_zero + src_offset, src_offset < N);
77 - int dst_offset =
78 - blockIdx.y * 128 + warp_id * 32 + (lane_id % 8) * 4 + lane_id / 8;
79 - if (dst_offset < N_32align) {
80 - B_scale_result[dst_offset] = b_scale_reg;
81 - if (B_zero != nullptr) B_zero_result[dst_offset] = b_zero_reg;
82 - }
83 - }
84 -}
85 -
86 -template <typename FType>
87 -void rearrange_kn_weight_as_n32k16_order_ldg16(
88 - const uint8_t* B, const FType* B_scale, const FType* B_zero,
89 - uint8_t* B_result, FType* B_scale_result, FType* B_zero_result,
90 - const int64_t K, const int64_t N, const int64_t N_32align,
91 - cudaStream_t stream) {
92 - if (N % 16 != 0 || K % 16 != 0) {
93 - std::cerr << "Now only support N and K is multiples of 16" << std::endl;
94 - }
95 - const int BLOCK = 128;
96 - int grid_x = (K + 64 - 1) / 64 + 1;
97 - int grid_y = (N + 128 - 1) / 128;
98 - dim3 grid(grid_x, grid_y);
99 -
100 - rearrange_kn_weight_as_n32k16_order_ldg16_kernel<FType>
101 - <<<grid, BLOCK, 0, stream>>>(B, B_scale, B_zero, B_result, B_scale_result,
102 - B_zero_result, K, N, N_32align);
103 -}
104 -} // namespace allspark
105 -
106 -void rearrange_kn_weight_as_n32k16_order(
107 - torch::stable::Tensor const& b_qweight,
108 - torch::stable::Tensor const& b_scales,
109 - std::optional<torch::stable::Tensor> const& b_zeros, bool has_zp,
110 - torch::stable::Tensor& b_qweight_reorder,
111 - torch::stable::Tensor& b_scales_reorder,
112 - std::optional<torch::stable::Tensor> const& b_zeros_reorder,
113 - const int64_t K, const int64_t N, const int64_t N_32align) {
114 - // Verify device and strides
115 - STD_TORCH_CHECK(b_qweight.device().is_cuda(), "b_qweight is not on GPU");
116 - STD_TORCH_CHECK(b_qweight.is_contiguous(), "b_qweight is not contiguous");
117 -
118 - STD_TORCH_CHECK(b_scales.device().is_cuda(), "b_scales is not on GPU");
119 - STD_TORCH_CHECK(b_scales.is_contiguous(), "b_scales is not contiguous");
120 -
121 - STD_TORCH_CHECK(b_qweight_reorder.device().is_cuda(),
122 - "b_qweight_reorder is not on GPU");
123 - STD_TORCH_CHECK(b_qweight_reorder.is_contiguous(),
124 - "b_qweight_reorder is not contiguous");
125 -
126 - STD_TORCH_CHECK(b_scales_reorder.device().is_cuda(),
127 - "b_scales_reorder is not on GPU");
128 - STD_TORCH_CHECK(b_scales_reorder.is_contiguous(),
129 - "b_scales_reorder is not contiguous");
130 -
131 - if (has_zp) {
132 - STD_TORCH_CHECK(b_zeros.value().device().is_cuda(),
133 - "b_zeros is not on GPU");
134 - STD_TORCH_CHECK(b_zeros.value().is_contiguous(),
135 - "b_zeros is not contiguous");
136 -
137 - STD_TORCH_CHECK(b_zeros_reorder.value().device().is_cuda(),
138 - "b_zeros_reorder is not on GPU");
139 - STD_TORCH_CHECK(b_zeros_reorder.value().is_contiguous(),
140 - "b_zeros_reorder is not contiguous");
141 - }
142 -
143 - const uint8_t* matB = reinterpret_cast<const uint8_t*>(b_qweight.data_ptr());
144 - const void* b_scale = b_scales.data_ptr();
145 - const void* b_zero = has_zp ? b_zeros.value().data_ptr() : nullptr;
146 -
147 - uint8_t* matB_reorder =
148 - reinterpret_cast<uint8_t*>(b_qweight_reorder.mutable_data_ptr());
149 - void* b_scale_reorder = b_scales_reorder.mutable_data_ptr();
150 - void* b_zero_reorder =
151 - has_zp ? b_zeros_reorder.value().mutable_data_ptr() : nullptr;
152 -
153 - const torch::stable::accelerator::DeviceGuard device_guard(
154 - b_qweight.get_device_index());
155 - cudaStream_t stream = get_current_cuda_stream();
156 - if (b_scales.scalar_type() == torch::headeronly::ScalarType::Half) {
157 - allspark::rearrange_kn_weight_as_n32k16_order_ldg16<__half>(
158 - matB, reinterpret_cast<const __half*>(b_scale),
159 - reinterpret_cast<const __half*>(b_zero), matB_reorder,
160 - reinterpret_cast<__half*>(b_scale_reorder),
161 - reinterpret_cast<__half*>(b_zero_reorder), K, N, N_32align, stream);
162 - } else if (b_scales.scalar_type() ==
163 - torch::headeronly::ScalarType::BFloat16) {
164 - allspark::rearrange_kn_weight_as_n32k16_order_ldg16<__nv_bfloat16>(
165 - matB, reinterpret_cast<const __nv_bfloat16*>(b_scale),
166 - reinterpret_cast<const __nv_bfloat16*>(b_zero), matB_reorder,
167 - reinterpret_cast<__nv_bfloat16*>(b_scale_reorder),
168 - reinterpret_cast<__nv_bfloat16*>(b_zero_reorder), K, N, N_32align,
169 - stream);
170 - }
171 -}
172 -
173 -STABLE_TORCH_LIBRARY_IMPL(_C, CUDA, m) {
174 - m.impl("rearrange_kn_weight_as_n32k16_order",
175 - TORCH_BOX(&rearrange_kn_weight_as_n32k16_order));
176 -}
csrc/libtorch_stable/quantization/gptq_allspark/allspark_utils.cuh deleted
-387
@@ -1,387 +0,0 @@
1 -#pragma once
2 -
3 -#include <cuda_bf16.h>
4 -#include <cuda_fp16.h>
5 -#include <cuda_runtime.h>
6 -
7 -#include <iostream>
8 -
9 -#include "libtorch_stable/quantization/marlin/marlin_dtypes.cuh"
10 -using marlin::MarlinScalarType2;
11 -
12 -namespace allspark {
13 -
14 -#define CHECK_CUDA(cmd) \
15 - do { \
16 - cudaError_t cuda_status = cmd; \
17 - if (cuda_status != cudaSuccess) { \
18 - std::string err_str = cudaGetErrorString(cuda_status); \
19 - std::cerr << "Failed: " << __FILE__ << ":" << __LINE__ << " " \
20 - << err_str; \
21 - exit(-1); \
22 - } \
23 - } while (0)
24 -
25 -#define CHECK_CUBLAS(cmd) \
26 - do { \
27 - cublasStatus_t cublas_status = cmd; \
28 - if (cublas_status != CUBLAS_STATUS_SUCCESS) { \
29 - std::cerr << "Failed: " << __FILE__ << ":" << __LINE__ << " " \
30 - << cublas_status << std::endl; \
31 - exit(-1); \
32 - } \
33 - } while (0)
34 -
35 -template <typename FType, typename QType>
36 -struct SM8x_GEMM_W8A16_Splitk_Params {
37 - const FType* A_ptr;
38 - const QType* B_ptr;
39 - const FType* B_scale_ptr;
40 - const FType* B_zero_ptr;
41 - FType* C_ptr;
42 - int M;
43 - int N;
44 - int K;
45 - int SplitK;
46 - int GroupCnt;
47 - int GroupSize;
48 - FType* C_split_ptr; // for non-fused splitk reduce
49 - float* C_tmp_ptr; // for fused splitk reduce
50 - uint32_t* red_count_ptr; // for fused splitk reduce
51 -};
52 -
53 -struct alignas(16) BlockTileSplitkParams {
54 - int Mtile;
55 - int Ntile;
56 - int SplitK;
57 - bool EnableFuse;
58 -};
59 -
60 -template <typename FType, int BLOCK, int N_MATRIX>
61 -__global__ void f16_gemm_splitk_reduce_kernel(const FType* C_split, FType* C,
62 - uint32_t n, uint32_t n_matrix,
63 - uint32_t matrix_size) {
64 - auto idx = blockIdx.x * BLOCK + threadIdx.x;
65 -
66 - if (idx >= matrix_size) {
67 - return;
68 - }
69 -
70 - float sum = 0.f;
71 -
72 - int n_mat = N_MATRIX > 0 ? N_MATRIX : (int)n_matrix;
73 - for (int i = 0; i < n_mat; ++i) {
74 - sum += MarlinScalarType2<FType>::num2float(C_split[idx + i * matrix_size]);
75 - }
76 -
77 - C[idx] = MarlinScalarType2<FType>::float2num(sum);
78 -}
79 -
80 -template <typename FType>
81 -void f16_gemm_splitk_reduce(const FType* C_split, FType* C, const uint32_t m,
82 - const uint32_t n, const uint32_t n_matrix,
83 - cudaStream_t stream) {
84 - const int BLOCK = 128;
85 - uint32_t matrix_size = m * n;
86 - int grid = (matrix_size + BLOCK - 1) / BLOCK;
87 -
88 - void (*kernel)(const FType*, FType*, uint32_t, uint32_t, uint32_t) = nullptr;
89 -
90 - switch (n_matrix) {
91 - case 4:
92 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 4>;
93 - break;
94 - case 5:
95 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 5>;
96 - break;
97 - case 6:
98 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 6>;
99 - break;
100 - case 7:
101 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 7>;
102 - break;
103 - case 8:
104 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 8>;
105 - break;
106 - case 9:
107 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 9>;
108 - break;
109 - case 10:
110 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 10>;
111 - break;
112 - case 11:
113 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 11>;
114 - break;
115 - case 12:
116 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, 12>;
117 - break;
118 - default:
119 - kernel = f16_gemm_splitk_reduce_kernel<FType, BLOCK, -1>;
120 - break;
121 - }
122 -
123 - kernel<<<grid, BLOCK, 0, stream>>>(C_split, C, n, n_matrix, matrix_size);
124 -}
125 -
126 -template <typename T>
127 -struct HalfType;
128 -template <>
129 -struct HalfType<half> {
130 - using T1 = __half;
131 - using T2 = __half2;
132 -};
133 -template <>
134 -struct HalfType<__nv_bfloat16> {
135 - using T1 = __nv_bfloat16;
136 - using T2 = __nv_bfloat162;
137 -};
138 -
139 -// convert 64-bit pointer to 32-bit smem addr
140 -__device__ __forceinline__ uint32_t smem_u32addr(const void* smem_ptr) {
141 - uint32_t addr;
142 - asm("{.reg .u64 u64addr;\n"
143 - " cvta.to.shared.u64 u64addr, %1;\n"
144 - " cvt.u32.u64 %0, u64addr;}\n"
145 - : "=r"(addr)
146 - : "l"(smem_ptr));
147 -
148 - return addr;
149 -}
150 -
151 -template <typename T>
152 -__device__ __forceinline__ void ldg16_cg_0(T& r0, const void* ptr, bool guard) {
153 - static_assert(sizeof(T) == 2, "ldg16_cg_0: invalid T");
154 -
155 - asm volatile(
156 - "{.reg .pred p;\n"
157 - " setp.ne.b32 p, %2, 0;\n"
158 - " @!p mov.b16 %0, 0;\n"
159 -#if __CUDACC_VER_MAJOR__ >= 11 && __CUDACC_VER_MINOR__ >= 4 && \
160 - __CUDA_ARCH__ >= 750
161 - " @p ld.global.cg.L2::128B.b16 {%0}, [%1];}\n"
162 -#else
163 - " @p ld.global.ca.b16 {%0}, [%1];}\n"
164 -#endif
165 - : "=h"(reinterpret_cast<uint16_t&>(r0))
166 - : "l"(ptr), "r"((int)guard));
167 -}
168 -
169 -template <typename T>
170 -__device__ __forceinline__ void ldg64_ca(T& r0, T& r1, const void* ptr,
171 - bool guard) {
172 - static_assert(sizeof(T) == 4, "ldg64_ca: invalid T");
173 -
174 - asm volatile(
175 - "{.reg .pred p;\n"
176 - " setp.ne.b32 p, %3, 0;\n"
177 -#if __CUDACC_VER_MAJOR__ >= 11 && __CUDACC_VER_MINOR__ >= 4 && \
178 - __CUDA_ARCH__ >= 750
179 - " @p ld.global.ca.L2::128B.v2.b32 {%0, %1}, [%2];}\n"
180 -#else
181 - " @p ld.global.ca.v2.b32 {%0, %1}, [%2];}\n"
182 -#endif
183 - : "=r"(reinterpret_cast<uint32_t&>(r0)),
184 - "=r"(reinterpret_cast<uint32_t&>(r1))
185 - : "l"(ptr), "r"((int)guard));
186 -}
187 -
188 -template <typename T>
189 -__device__ __forceinline__ void ldg128_cg_0(T& r0, T& r1, T& r2, T& r3,
190 - const void* ptr, bool guard) {
191 - static_assert(sizeof(T) == 4, "ldg128_cg_0: invalid T");
192 -
193 - asm volatile(
194 - "{.reg .pred p;\n"
195 - " setp.ne.b32 p, %5, 0;\n"
196 - " @!p mov.b32 %0, 0;\n"
197 - " @!p mov.b32 %1, 0;\n"
198 - " @!p mov.b32 %2, 0;\n"
199 - " @!p mov.b32 %3, 0;\n"
200 -#if __CUDACC_VER_MAJOR__ >= 11 && __CUDACC_VER_MINOR__ >= 4 && \
201 - __CUDA_ARCH__ >= 750
202 - " @p ld.global.cg.L2::128B.v4.b32 {%0, %1, %2, %3}, [%4];}\n"
203 -#else
204 - " @p ld.global.cg.v4.b32 {%0, %1, %2, %3}, [%4];}\n"
205 -#endif
206 - : "=r"(reinterpret_cast<uint32_t&>(r0)),
207 - "=r"(reinterpret_cast<uint32_t&>(r1)),
208 - "=r"(reinterpret_cast<uint32_t&>(r2)),
209 - "=r"(reinterpret_cast<uint32_t&>(r3))
210 - : "l"(ptr), "r"((int)guard));
211 -}
212 -
213 -template <typename T>
214 -__device__ __forceinline__ void lds128(T& reg0, T& reg1, T& reg2, T& reg3,
215 - const uint32_t addr) {
216 - static_assert(sizeof(T) == 4, "lds128: invalid T");
217 -
218 - asm volatile("ld.shared.v4.b32 {%0, %1, %2, %3}, [%4];\n"
219 - : "=r"(reinterpret_cast<uint32_t&>(reg0)),
220 - "=r"(reinterpret_cast<uint32_t&>(reg1)),
221 - "=r"(reinterpret_cast<uint32_t&>(reg2)),
222 - "=r"(reinterpret_cast<uint32_t&>(reg3))
223 - : "r"(addr));
224 -}
225 -
226 -template <typename T>
227 -__device__ __forceinline__ void stg128(const T& r0, const T& r1, const T& r2,
228 - const T& r3, const void* ptr,
229 - bool guard) {
230 - static_assert(sizeof(T) == 4, "stg128: invalid T");
231 -
232 - asm volatile(
233 - "{.reg .pred p;\n"
234 - " setp.ne.b32 p, %1, 0;\n"
235 - " @p st.global.v4.b32 [%0], {%2, %3, %4, %5};}\n"
236 - :
237 - : "l"(ptr), "r"((int)guard), "r"(reinterpret_cast<const uint32_t&>(r0)),
238 - "r"(reinterpret_cast<const uint32_t&>(r1)),
239 - "r"(reinterpret_cast<const uint32_t&>(r2)),
240 - "r"(reinterpret_cast<const uint32_t&>(r3)));
241 -}
242 -
243 -template <typename T>
244 -__device__ __forceinline__ void ldsm_4(T& r0, T& r1, T& r2, T& r3,
245 - const uint32_t& addr) {
246 - static_assert(sizeof(T) == 4, "ldsm_4: invalid T");
247 -#if (__CUDA_ARCH__ >= 750) && (__CUDACC_VER_MAJOR__ >= 11)
248 - asm volatile(
249 - "ldmatrix.sync.aligned.m8n8.x4.shared.b16 {%0, %1, %2, %3}, [%4];\n"
250 - : "=r"(reinterpret_cast<uint32_t&>(r0)),
251 - "=r"(reinterpret_cast<uint32_t&>(r1)),
252 - "=r"(reinterpret_cast<uint32_t&>(r2)),
253 - "=r"(reinterpret_cast<uint32_t&>(r3))
254 - : "r"(addr));
255 -#endif
256 -}
257 -
258 -template <typename FType>
259 -__device__ __forceinline__ void hmma16816_f32(float (&d)[4],
260 - const uint32_t (&a)[4],
261 - const uint32_t (&b)[2]);
262 -
263 -template <>
264 -__device__ __forceinline__ void hmma16816_f32<__half>(float (&d)[4],
265 - const uint32_t (&a)[4],
266 - const uint32_t (&b)[2]) {
267 -#if (__CUDA_ARCH__ >= 800) && (__CUDACC_VER_MAJOR__ >= 11)
268 - asm volatile(
269 - "mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, "
270 - "{%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};\n"
271 - : "+f"(d[0]), "+f"(d[1]), "+f"(d[2]), "+f"(d[3])
272 - : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]));
273 -#endif
274 -}
275 -
276 -template <>
277 -__device__ __forceinline__ void hmma16816_f32<__nv_bfloat16>(
278 - float (&d)[4], const uint32_t (&a)[4], const uint32_t (&b)[2]) {
279 -#if (__CUDA_ARCH__ >= 800) && (__CUDACC_VER_MAJOR__ >= 11)
280 - asm volatile(
281 - "mma.sync.aligned.m16n8k16.row.col.f32.bf16.bf16.f32 {%0, %1, %2, %3}, "
282 - "{%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};\n"
283 - : "+f"(d[0]), "+f"(d[1]), "+f"(d[2]), "+f"(d[3])
284 - : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]));
285 -#endif
286 -}
287 -
288 -template <int SIZE_IN_BYTES>
289 -__device__ __forceinline__ void cp_async(const uint32_t smem_addr,
290 - const void* gmem_ptr,
291 - const int src_in_bytes, bool guard) {
292 - static_assert(
293 - (SIZE_IN_BYTES == 4 || SIZE_IN_BYTES == 8 || SIZE_IN_BYTES == 16),
294 - "Size is not supported");
295 -#if __CUDACC_VER_MAJOR__ >= 11 && __CUDA_ARCH__ >= 800
296 - asm volatile(
297 - "{.reg.pred p;\n"
298 - " setp.ne.b32 p, %4, 0;\n"
299 - #if __CUDACC_VER_MINOR__ >= 4
300 - " @p cp.async.cg.shared.global.L2::256B [%0], [%1], %2, %3;}\n"
301 - #else
302 - " @p cp.async.cg.shared.global [%0], [%1], %2, %3;}\n"
303 - #endif
304 - ::"r"(smem_addr),
305 - "l"(gmem_ptr), "n"(SIZE_IN_BYTES), "r"(src_in_bytes), "r"((int)guard));
306 -#endif
307 -}
308 -
309 -__device__ __forceinline__ void cp_async_commit_group() {
310 -#if __CUDACC_VER_MAJOR__ >= 11 && __CUDA_ARCH__ >= 800
311 - asm volatile("cp.async.commit_group;\n");
312 -#endif
313 -}
314 -
315 -template <int N>
316 -__device__ __forceinline__ void cp_asyc_wait_group() {
317 -#if __CUDACC_VER_MAJOR__ >= 11 && __CUDA_ARCH__ >= 800
318 - asm volatile("cp.async.wait_group %0;\n" : : "n"(N));
319 -#endif
320 -}
321 -
322 -template <typename T>
323 -__device__ __forceinline__ void cvt_8bx4_to_16bx4_bias128(const uint32_t& idata,
324 - T* fdata);
325 -
326 -template <>
327 -// fast conversion: 4xuint8 to 4xhalf, subtracting bias = 128
328 -__device__ __forceinline__ void cvt_8bx4_to_16bx4_bias128<__half2>(
329 - const uint32_t& idata, __half2* fdata) {
330 - uint32_t i10, i32;
331 - asm volatile(
332 - "prmt.b32 %0, %2, 0x64, 0x4140;"
333 - "prmt.b32 %1, %2, 0x64, 0x4342;"
334 - : "=r"(i10), "=r"(i32)
335 - : "r"(idata));
336 -
337 - static constexpr uint32_t MAGIC_NUM = 0x64806480;
338 - fdata[0] = __hsub2(reinterpret_cast<const __half2&>(i10),
339 - reinterpret_cast<const __half2&>(MAGIC_NUM));
340 - fdata[1] = __hsub2(reinterpret_cast<const __half2&>(i32),
341 - reinterpret_cast<const __half2&>(MAGIC_NUM));
342 -}
343 -
344 -template <>
345 -// fast conversion: 4xuint8 to 4xbfloat16, subtracting bias = 128
346 -// reference from marlin fast implementation
347 -__device__ __forceinline__ void cvt_8bx4_to_16bx4_bias128<__nv_bfloat162>(
348 - const uint32_t& idata, __nv_bfloat162* fdata) {
349 - float fp32_imd[4];
350 - uint32_t* fp32_imd_casted = reinterpret_cast<uint32_t*>(fp32_imd);
351 - asm volatile(
352 - "prmt.b32 %0, %4, 0x4B000000, 0x7650;"
353 - "prmt.b32 %1, %4, 0x4B000000, 0x7651;"
354 - "prmt.b32 %2, %4, 0x4B000000, 0x7652;"
355 - "prmt.b32 %3, %4, 0x4B000000, 0x7653;"
356 - : "=r"(fp32_imd_casted[0]), "=r"(fp32_imd_casted[1]),
357 - "=r"(fp32_imd_casted[2]), "=r"(fp32_imd_casted[3])
358 - : "r"(idata));
359 -
360 - fp32_imd[0] -= 8388736.f;
361 - fp32_imd[1] -= 8388736.f;
362 - fp32_imd[2] -= 8388736.f;
363 - fp32_imd[3] -= 8388736.f;
364 -
365 - uint32_t* bf16_res = reinterpret_cast<uint32_t*>(fdata);
366 - asm volatile(
367 - "prmt.b32 %0, %2, %3, 0x7632;"
368 - "prmt.b32 %1, %4, %5, 0x7632;"
369 - : "=r"(bf16_res[0]), "=r"(bf16_res[1])
370 - : "r"(fp32_imd_casted[0]), "r"(fp32_imd_casted[1]),
371 - "r"(fp32_imd_casted[2]), "r"(fp32_imd_casted[3]));
372 -}
373 -
374 -static __device__ nv_bfloat162 inline num2num2(const nv_bfloat16 x) {
375 -#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
376 - assert(false);
377 -#else
378 - return __bfloat162bfloat162(x);
379 -#endif
380 - __builtin_unreachable(); // Suppress missing return statement warning
381 -}
382 -
383 -static __device__ half2 inline num2num2(const half x) {
384 - return __half2half2(x);
385 -}
386 -
387 -} // namespace allspark
csrc/libtorch_stable/torch_bindings.cpp
-18
@@ -327,21 +327,6 @@ STABLE_TORCH_LIBRARY_FRAGMENT(_C, ops) {
327 // BF16/FP32 x FP32 -> FP32 router GEMM for H=3072, E=256, M<=32 (SM90+).
328 // conditionally compiled so impl registration is in source file
329 ops.def("fp32_router_gemm(Tensor! output, Tensor mat_a, Tensor mat_b) -> ()");
330 -
331 - // reorder weight for AllSpark Ampere W8A16 Fused Gemm kernel
332 - ops.def(
333 - "rearrange_kn_weight_as_n32k16_order(Tensor b_qweight, Tensor b_scales, "
334 - "Tensor? b_zeros, "
335 - "bool has_zp, Tensor! b_qweight_reorder, Tensor! b_scales_reorder, "
336 - "Tensor!? b_zeros_reorder, "
337 - "int K, int N, int N_32align) -> ()");
338 -
339 - // AllSpark quantization ops
340 - ops.def(
341 - "allspark_w8a16_gemm(Tensor a, Tensor b_qweight, Tensor b_scales, "
342 - "Tensor? b_qzeros, "
343 - "SymInt n, SymInt group_size, SymInt sm_count, SymInt sm_version, SymInt "
344 - "CUBLAS_M_THRESHOLD, bool has_zp, bool n32k16_reorder) -> Tensor");
330 #endif
331
332 // Merge attn states
@@ -794,9 +779,6 @@ STABLE_TORCH_LIBRARY_IMPL(_C, CUDA, ops) {
779
780 // DSV3 fused A GEMM: conditionally compiled so impl registration is in
781 // source file (dsv3_fused_a_gemm.cu)
797 -
798 - // AllSpark ops: conditionally compiled so impl registrations are in source
799 - // files (allspark_repack.cu and allspark_qgemm_w8a16.cu)
782 #endif
783
784 ops.impl("merge_attn_states", TORCH_BOX(&merge_attn_states));
tests/kernels/quantization/test_allspark_gemm.py deleted
-128
@@ -1,128 +0,0 @@
1 -# SPDX-License-Identifier: Apache-2.0
2 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 -import pytest
4 -import torch
5 -
6 -from tests.kernels.utils import DEFAULT_OPCHECK_TEST_UTILS, opcheck
7 -from vllm import _custom_ops as ops
8 -from vllm.model_executor.layers.quantization.utils.allspark_utils import (
9 - ALLSPARK_AMPERE_K_ALIGN,
10 - ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD,
11 - ALLSPARK_AMPERE_N_ALIGN,
12 -)
13 -from vllm.model_executor.layers.quantization.utils.quant_utils import quantize_weights
14 -from vllm.platforms import current_platform
15 -from vllm.scalar_type import scalar_types
16 -from vllm.utils.platform_utils import num_compute_units
17 -
18 -
19 -def is_gptq_allspark_supported(min_capability: int, max_capability: int) -> bool:
20 - if not current_platform.is_cuda():
21 - return False
22 -
23 - capability = current_platform.get_device_capability()
24 - assert capability is not None
25 -
26 - return (
27 - capability.to_int() >= min_capability and capability.to_int() <= max_capability
28 - )
29 -
30 -
31 -MNK_FACTORS = [
32 - (1, 4, 8),
33 - (13, 17, 67),
34 - (26, 37, 13),
35 - (48, 16, 24),
36 - (67, 13, 88),
37 - (257, 13, 11),
38 - (658, 13, 11),
39 - (1033, 9, 17),
40 -]
41 -
42 -DTYPES = [torch.float16, torch.bfloat16]
43 -HAS_ZP_OPTS = [False, True]
44 -
45 -
46 -def compute_max_diff(output, output_ref):
47 - return torch.mean(torch.abs(output - output_ref)) / torch.mean(
48 - torch.abs(output_ref)
49 - )
50 -
51 -
52 -def rand_data(shape, dtype=torch.float16):
53 - return torch.randn(shape, dtype=dtype, device="cuda")
54 -
55 -
56 -@pytest.mark.skipif(
57 - not is_gptq_allspark_supported(80, 89),
58 - reason="AllSpark Ampere kernel is not supported on this GPU type.",
59 -)
60 -@pytest.mark.parametrize("mnk_factors", MNK_FACTORS)
61 -@pytest.mark.parametrize("group_size", [-1])
62 -@pytest.mark.parametrize("has_zp", HAS_ZP_OPTS)
63 -@pytest.mark.parametrize("dtype", DTYPES)
64 -def test_gptq_allspark_gemm_ampere(mnk_factors, group_size, has_zp, dtype):
65 - m_factor, n_factor, k_factor = mnk_factors
66 - m = m_factor
67 - n = n_factor * ALLSPARK_AMPERE_N_ALIGN
68 - k = k_factor * ALLSPARK_AMPERE_K_ALIGN
69 -
70 - input = rand_data((m, k), dtype=dtype)
71 - weight = rand_data((k, n), dtype=dtype)
72 -
73 - # Quantize weights.
74 - w_ref, qw, s, zp = quantize_weights(
75 - weight, scalar_types.uint8b128, group_size, has_zp
76 - )
77 -
78 - qw = qw.to(torch.uint8)
79 - if has_zp:
80 - zp = zp.to(dtype)
81 - properties = torch.cuda.get_device_properties(qw.device.index)
82 - sm_count = num_compute_units(qw.device.index)
83 - sm_version = properties.major * 10 + properties.minor
84 -
85 - n_32align = (n + 32 - 1) // 32 * 32
86 -
87 - qw_reorder, s_reorder, zp_reorder = ops.allspark_repack_weight(qw, s, zp, has_zp)
88 - opcheck(
89 - torch.ops._C.rearrange_kn_weight_as_n32k16_order,
90 - (qw, s, zp, has_zp, qw_reorder, s_reorder, zp_reorder, k, n, n_32align),
91 - )
92 -
93 - opcheck(
94 - torch.ops._C.allspark_w8a16_gemm,
95 - (
96 - input,
97 - qw_reorder,
98 - s_reorder,
99 - zp_reorder,
100 - n,
101 - group_size,
102 - sm_count,
103 - sm_version,
104 - ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD,
105 - has_zp,
106 - True,
107 - ),
108 - test_utils=DEFAULT_OPCHECK_TEST_UTILS,
109 - )
110 - output = ops.allspark_w8a16_gemm(
111 - input,
112 - qw_reorder,
113 - s_reorder,
114 - zp_reorder,
115 - n,
116 - group_size,
117 - sm_count,
118 - sm_version,
119 - ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD,
120 - has_zp,
121 - True,
122 - )
123 -
124 - output_ref = torch.matmul(input, w_ref)
125 - torch.accelerator.synchronize()
126 - max_diff = compute_max_diff(output, output_ref)
127 -
128 - assert max_diff < 0.04
vllm/_custom_ops.py
-104
@@ -732,26 +732,6 @@ def moe_gptq_gemm_rdna3(
732 )
733
734
735 -if hasattr(torch.ops._C, "allspark_w8a16_gemm"):
736 -
737 - @register_fake("_C::allspark_w8a16_gemm")
738 - def _allspark_w8a16_gemm_fake(
739 - a: torch.Tensor,
740 - b_qweight: torch.Tensor,
741 - b_scales: torch.Tensor,
742 - b_qzeros: torch.Tensor | None,
743 - n: torch.SymInt,
744 - group_size: torch.SymInt,
745 - sm_count: torch.SymInt,
746 - sm_version: torch.SymInt,
747 - CUBLAS_M_THRESHOLD: torch.SymInt,
748 - has_zp: bool,
749 - n32k16_reorder: bool,
750 - ) -> torch.Tensor:
751 - m = a.size(0)
752 - return torch.empty((m, n), device=a.device, dtype=a.dtype)
753 -
754 -
735 # cutlass
736 def cutlass_scaled_mm_supports_fp4(cuda_device_capability: int) -> bool:
737 return torch.ops._C.cutlass_scaled_mm_supports_fp4(cuda_device_capability)
@@ -1911,90 +1891,6 @@ def scaled_fp8_quant(
1891 return output, scale
1892
1893
1914 -# gptq allspark
1915 -def allspark_repack_weight(
1916 - qweight: torch.Tensor,
1917 - scale: torch.Tensor,
1918 - zero_point: torch.Tensor | None = None,
1919 - has_zp: bool = False,
1920 -) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
1921 - """Rearrange qweight, scale, and zero_point(if asymmetric) to n32k16 format
1922 - for Ampere W8A16 Fused Gemm kernel
1923 -
1924 - Args:
1925 - qweight: uint8 weight tensor, original k x n format.
1926 - scale: fp16/bf16 weight scale tensor, 1 x n format.
1927 - zero_point: fp16/bf16 weight zero_point tensor, 1 x n format.
1928 - Must be provided for asymmetric quantization.
1929 - has_zp: if use symmetric quantization, has_zp = False.
1930 - if use asymmetric quantization, has_zp = True.
1931 -
1932 - Returns:
1933 - tuple[torch.Tensor, torch.Tensor, torch.Tensor | None] :
1934 - rearranged weight, scale, and optionally zero_point.
1935 -
1936 - """
1937 - K = qweight.shape[0]
1938 - N = qweight.shape[1]
1939 - N_32align = (N + 32 - 1) // 32 * 32
1940 -
1941 - qweight_reorder = torch.empty(
1942 - (N_32align, K), device=qweight.device, dtype=qweight.dtype
1943 - )
1944 - scale_reorder = torch.empty((1, N_32align), device=scale.device, dtype=scale.dtype)
1945 - zero_point_reorder = None
1946 - if has_zp:
1947 - assert zero_point is not None, (
1948 - "zero_point must be provided for asymmetric quantization."
1949 - )
1950 - zero_point_reorder = torch.empty(
1951 - (1, N_32align), device=zero_point.device, dtype=zero_point.dtype
1952 - )
1953 -
1954 - torch.ops._C.rearrange_kn_weight_as_n32k16_order(
1955 - qweight,
1956 - scale,
1957 - zero_point,
1958 - has_zp,
1959 - qweight_reorder,
1960 - scale_reorder,
1961 - zero_point_reorder,
1962 - K,
1963 - N,
1964 - N_32align,
1965 - )
1966 -
1967 - return qweight_reorder, scale_reorder, zero_point_reorder
1968 -
1969 -
1970 -def allspark_w8a16_gemm(
1971 - a: torch.Tensor,
1972 - b_qweight: torch.Tensor,
1973 - b_scales: torch.Tensor,
1974 - b_qzeros: torch.Tensor | None,
1975 - n: int,
1976 - group_size: int,
1977 - sm_count: int,
1978 - sm_version: int,
1979 - CUBLAS_M_THRESHOLD: int,
1980 - has_zp: bool,
1981 - n32k16_reorder: bool,
1982 -) -> torch.Tensor:
1983 - return torch.ops._C.allspark_w8a16_gemm(
1984 - a,
1985 - b_qweight,
1986 - b_scales,
1987 - b_qzeros,
1988 - n,
1989 - group_size,
1990 - sm_count,
1991 - sm_version,
1992 - CUBLAS_M_THRESHOLD,
1993 - has_zp,
1994 - n32k16_reorder,
1995 - )
1996 -
1997 -
1894 # int8
1895 def scaled_int8_quant(
1896 input: torch.Tensor,
vllm/model_executor/kernels/linear/__init__.py
-5
@@ -26,9 +26,6 @@ from vllm.model_executor.kernels.linear.mixed_precision import (
26 MPLinearKernel,
27 MPLinearLayerConfig,
28 )
29 -from vllm.model_executor.kernels.linear.mixed_precision.allspark import (
30 - AllSparkLinearKernel,
31 -)
29 from vllm.model_executor.kernels.linear.mixed_precision.conch import (
30 ConchLinearKernel,
31 )
@@ -504,7 +501,6 @@ _POSSIBLE_KERNELS: dict[PlatformEnum, list[type[MPLinearKernel]]] = {
501 PlatformEnum.CUDA: [
502 CutlassW4A8LinearKernel,
503 MacheteLinearKernel,
507 - AllSparkLinearKernel,
504 MarlinLinearKernel,
505 ConchLinearKernel,
506 ExllamaLinearKernel,
@@ -1272,7 +1268,6 @@ __all__ = [
1268 "ZentorchWNA16LinearKernel",
1269 "MPLinearKernel",
1270 "MPLinearLayerConfig",
1275 - "AllSparkLinearKernel",
1271 "ConchLinearKernel",
1272 "CPUWNA16LinearKernel",
1273 "CutlassW4A8LinearKernel",
vllm/model_executor/kernels/linear/mixed_precision/__init__.py
-4
@@ -1,9 +1,6 @@
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 -from vllm.model_executor.kernels.linear.mixed_precision.allspark import (
5 - AllSparkLinearKernel,
6 -)
4 from vllm.model_executor.kernels.linear.mixed_precision.conch import (
5 ConchLinearKernel,
6 )
@@ -52,7 +49,6 @@ from vllm.model_executor.kernels.linear.mixed_precision.zentorch import (
49 __all__ = [
50 "MPLinearKernel",
51 "MPLinearLayerConfig",
55 - "AllSparkLinearKernel",
52 "ConchLinearKernel",
53 "CPUWNA16LinearKernel",
54 "CutlassW4A8LinearKernel",
vllm/model_executor/kernels/linear/mixed_precision/allspark.py deleted
-113
@@ -1,113 +0,0 @@
1 -# SPDX-License-Identifier: Apache-2.0
2 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 -
4 -
5 -import torch
6 -
7 -from vllm import _custom_ops as ops
8 -from vllm.model_executor.layers.quantization.utils import replace_parameter
9 -from vllm.model_executor.layers.quantization.utils.allspark_utils import (
10 - ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD,
11 - check_allspark_supported_dtype_shape,
12 -)
13 -from vllm.model_executor.parameter import BasevLLMParameter, permute_param_layout_
14 -from vllm.utils.platform_utils import num_compute_units
15 -
16 -from .MPLinearKernel import MPLinearKernel, MPLinearLayerConfig
17 -
18 -
19 -class AllSparkLinearKernel(MPLinearKernel):
20 - @classmethod
21 - def get_min_capability(cls) -> int:
22 - return 80
23 -
24 - @classmethod
25 - def can_implement(cls, c: MPLinearLayerConfig) -> tuple[bool, str | None]:
26 - if c.zero_points:
27 - return False, "Zero points currently not supported by AllSpark"
28 -
29 - return check_allspark_supported_dtype_shape(
30 - c.partition_weight_shape[0], # in_features
31 - c.partition_weight_shape[1], # out_features
32 - c.group_size,
33 - c.weight_type,
34 - c.act_type,
35 - )
36 -
37 - # note assumes that
38 - # `weight_packed` is: {input_dim = 0, output_dim = 1, packed_dim = 0}
39 - # `weight_scale` is: {input_dim = 0, output_dim = 1}
40 - def process_weights_after_loading(self, layer: torch.nn.Module) -> None:
41 - device = getattr(layer, self.w_q_name).device
42 - c = self.config
43 -
44 - # prepare the parameters required for the kernel
45 - properties = torch.cuda.get_device_properties(device.index)
46 - sm_count = num_compute_units(device.index)
47 - sm_version = properties.major * 10 + properties.minor
48 - gemm_args = {}
49 - gemm_args["sm_count"] = sm_count
50 - gemm_args["sm_version"] = sm_version
51 -
52 - self.gemm_args = gemm_args
53 -
54 - # transform param weight, scale
55 - old_weight_param = getattr(layer, self.w_q_name)
56 - old_scale_param = getattr(layer, self.w_s_name)
57 -
58 - assert isinstance(old_weight_param, BasevLLMParameter)
59 - permute_param_layout_(old_weight_param, input_dim=0, output_dim=1, packed_dim=0)
60 -
61 - assert isinstance(old_scale_param, BasevLLMParameter)
62 - permute_param_layout_(old_scale_param, input_dim=0, output_dim=1)
63 -
64 - # unpack weight from K / 4 x N int32 to K x N uint8
65 - new_weight_param = torch.nn.Parameter(
66 - old_weight_param.data, requires_grad=False
67 - )
68 - new_weight_param.data = (
69 - new_weight_param.data.t().contiguous().view(dtype=torch.uint8)
70 - )
71 - new_weight_param.data = new_weight_param.data.t().contiguous()
72 -
73 - new_scale_param = torch.nn.Parameter(old_scale_param.data, requires_grad=False)
74 -
75 - # reorder K x N weight as N32K16 format for Ampere W8A16
76 - new_weight_param.data, new_scale_param.data, _ = ops.allspark_repack_weight(
77 - new_weight_param.data, new_scale_param.data, None, c.zero_points
78 - )
79 -
80 - replace_parameter(layer, self.w_q_name, new_weight_param.data)
81 - replace_parameter(layer, self.w_s_name, new_scale_param.data)
82 -
83 - def apply_weights(
84 - self,
85 - layer: torch.nn.Module,
86 - x: torch.Tensor,
87 - bias: torch.Tensor | None = None,
88 - ) -> torch.Tensor:
89 - c = self.config
90 - gemm_args = self.gemm_args
91 - w_q, w_s, _ = self._get_weight_params(layer)
92 -
93 - reshaped_x = x.reshape(-1, x.shape[-1])
94 - out_shape = x.shape[:-1] + (c.partition_weight_shape[1],)
95 -
96 - output = ops.allspark_w8a16_gemm(
97 - a=reshaped_x,
98 - b_qweight=w_q,
99 - b_scales=w_s,
100 - b_qzeros=None,
101 - n=c.partition_weight_shape[1],
102 - group_size=c.group_size,
103 - sm_count=gemm_args["sm_count"],
104 - sm_version=gemm_args["sm_version"],
105 - CUBLAS_M_THRESHOLD=ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD,
106 - has_zp=c.zero_points,
107 - n32k16_reorder=True,
108 - )
109 -
110 - if bias is not None:
111 - output.add_(bias) # In-place add
112 -
113 - return output.reshape(out_shape)
vllm/model_executor/layers/quantization/utils/allspark_utils.py deleted
-67
@@ -1,67 +0,0 @@
1 -# SPDX-License-Identifier: Apache-2.0
2 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 -
4 -import torch
5 -
6 -from vllm.platforms import current_platform
7 -from vllm.scalar_type import ScalarType, scalar_types
8 -
9 -ALLSPARK_AMPERE_M_CUBLAS_THRESHOLD = 1024
10 -ALLSPARK_SUPPORTED_QUANT_TYPES = [scalar_types.uint8b128]
11 -ALLSPARK_AMPERE_N_ALIGN = 16
12 -ALLSPARK_AMPERE_K_ALIGN = 16
13 -
14 -
15 -def check_allspark_supported_dtype_shape(
16 - input_size_per_partition: int,
17 - output_size_per_partition: int,
18 - group_size: int,
19 - weight_dtype: ScalarType,
20 - act_dtype: torch.dtype,
21 -):
22 - capability_tuple = current_platform.get_device_capability()
23 - device_capability = -1 if capability_tuple is None else capability_tuple.to_int()
24 -
25 - # For Ampere GPU
26 - if device_capability >= 80 and device_capability < 90:
27 - if group_size != -1:
28 - return (
29 - False,
30 - "For Ampere GPU, AllSpark does not support group_size "
31 - f"= {group_size}. Only group_size = -1 are supported.",
32 - )
33 -
34 - if weight_dtype not in ALLSPARK_SUPPORTED_QUANT_TYPES:
35 - return (
36 - False,
37 - "For Ampere GPU, AllSpark does not support "
38 - f"quant type ({weight_dtype}). Only quant type "
39 - f"({ALLSPARK_SUPPORTED_QUANT_TYPES}) are supported.",
40 - )
41 -
42 - if (
43 - input_size_per_partition % ALLSPARK_AMPERE_K_ALIGN != 0
44 - or output_size_per_partition % ALLSPARK_AMPERE_N_ALIGN != 0
45 - ):
46 - return (
47 - False,
48 - "AllSpark needs input_size_per_partition % "
49 - f"{ALLSPARK_AMPERE_K_ALIGN} = 0 and "
50 - f"output_size_per_partition % {ALLSPARK_AMPERE_N_ALIGN} = 0 "
51 - "for Ampere GPU optimized kernels.",
52 - )
53 -
54 - if act_dtype != torch.float16 and act_dtype != torch.bfloat16:
55 - return (
56 - False,
57 - "AllSpark only supports act_dtype = float16 or bfloat16,"
58 - f"for Ampere GPU, but got act_dtype = {act_dtype}.",
59 - )
60 - else:
61 - return (
62 - False,
63 - "AllSpark currently does not support "
64 - f"device_capability = {device_capability}.",
65 - )
66 -
67 - return True, None