main
cu 457 lines 18.5 KB
Raw
1 #include <cuda.h>
2 #include <cudaTypedefs.h>
3
4 #include <torch/csrc/stable/tensor.h>
5
6 #include "libtorch_stable/torch_utils.h"
7
8 #include "libtorch_stable/cutlass_extensions/common.hpp"
9
10 void cutlass_scaled_mm_sm75(torch::stable::Tensor& c,
11 torch::stable::Tensor const& a,
12 torch::stable::Tensor const& b,
13 torch::stable::Tensor const& a_scales,
14 torch::stable::Tensor const& b_scales,
15 std::optional<torch::stable::Tensor> const& bias);
16
17 void cutlass_scaled_mm_sm80(torch::stable::Tensor& c,
18 torch::stable::Tensor const& a,
19 torch::stable::Tensor const& b,
20 torch::stable::Tensor const& a_scales,
21 torch::stable::Tensor const& b_scales,
22 std::optional<torch::stable::Tensor> const& bias);
23
24 void cutlass_scaled_mm_sm89(torch::stable::Tensor& c,
25 torch::stable::Tensor const& a,
26 torch::stable::Tensor const& b,
27 torch::stable::Tensor const& a_scales,
28 torch::stable::Tensor const& b_scales,
29 std::optional<torch::stable::Tensor> const& bias);
30
31 #if defined ENABLE_SCALED_MM_SM90 && ENABLE_SCALED_MM_SM90
32 void cutlass_scaled_mm_sm90(torch::stable::Tensor& c,
33 torch::stable::Tensor const& a,
34 torch::stable::Tensor const& b,
35 torch::stable::Tensor const& a_scales,
36 torch::stable::Tensor const& b_scales,
37 std::optional<torch::stable::Tensor> const& bias);
38 #endif
39 #if defined ENABLE_CUTLASS_MOE_SM90 && ENABLE_CUTLASS_MOE_SM90
40 void cutlass_moe_mm_sm90(torch::stable::Tensor& out_tensors,
41 torch::stable::Tensor const& a_tensors,
42 torch::stable::Tensor const& b_tensors,
43 torch::stable::Tensor const& a_scales,
44 torch::stable::Tensor const& b_scales,
45 torch::stable::Tensor const& expert_offsets,
46 torch::stable::Tensor const& problem_sizes,
47 torch::stable::Tensor const& a_strides,
48 torch::stable::Tensor const& b_strides,
49 torch::stable::Tensor const& c_strides,
50 bool per_act_token, bool per_out_ch);
51
52 #endif
53
54 #if defined ENABLE_CUTLASS_MOE_SM100 && ENABLE_CUTLASS_MOE_SM100
55 void cutlass_moe_mm_sm100(torch::stable::Tensor& out_tensors,
56 torch::stable::Tensor const& a_tensors,
57 torch::stable::Tensor const& b_tensors,
58 torch::stable::Tensor const& a_scales,
59 torch::stable::Tensor const& b_scales,
60 torch::stable::Tensor const& expert_offsets,
61 torch::stable::Tensor const& problem_sizes,
62 torch::stable::Tensor const& a_strides,
63 torch::stable::Tensor const& b_strides,
64 torch::stable::Tensor const& c_strides,
65 bool per_act_token, bool per_out_ch);
66 #endif
67
68 #if defined ENABLE_SCALED_MM_SM120 && ENABLE_SCALED_MM_SM120
69 void cutlass_scaled_mm_sm120(torch::stable::Tensor& c,
70 torch::stable::Tensor const& a,
71 torch::stable::Tensor const& b,
72 torch::stable::Tensor const& a_scales,
73 torch::stable::Tensor const& b_scales,
74 std::optional<torch::stable::Tensor> const& bias);
75 #endif
76
77 #if defined ENABLE_SCALED_MM_SM100 && ENABLE_SCALED_MM_SM100
78 void cutlass_scaled_mm_sm100(torch::stable::Tensor& c,
79 torch::stable::Tensor const& a,
80 torch::stable::Tensor const& b,
81 torch::stable::Tensor const& a_scales,
82 torch::stable::Tensor const& b_scales,
83 std::optional<torch::stable::Tensor> const& bias);
84 #endif
85
86 #if (defined(ENABLE_CUTLASS_MOE_SM90) && ENABLE_CUTLASS_MOE_SM90) || \
87 (defined(ENABLE_CUTLASS_MOE_SM100) && ENABLE_CUTLASS_MOE_SM100) || \
88 (defined(ENABLE_CUTLASS_MOE_SM120) && ENABLE_CUTLASS_MOE_SM120)
89 void get_cutlass_moe_mm_data_caller(
90 const torch::stable::Tensor& topk_ids,
91 torch::stable::Tensor& expert_offsets,
92 torch::stable::Tensor& problem_sizes1,
93 torch::stable::Tensor& problem_sizes2,
94 torch::stable::Tensor& input_permutation,
95 torch::stable::Tensor& output_permutation, const int64_t num_experts,
96 const int64_t n, const int64_t k,
97 const std::optional<torch::stable::Tensor>& blockscale_offsets,
98 const bool is_gated);
99
100 void get_cutlass_moe_mm_problem_sizes_from_expert_offsets_caller(
101 const torch::stable::Tensor& expert_first_token_offset,
102 torch::stable::Tensor& problem_sizes1,
103 torch::stable::Tensor& problem_sizes2, const int64_t n, const int64_t k,
104 const bool swap_ab);
105
106 void get_cutlass_batched_moe_mm_data_caller(
107 torch::stable::Tensor& expert_offsets,
108 torch::stable::Tensor& problem_sizes1,
109 torch::stable::Tensor& problem_sizes2,
110 const torch::stable::Tensor& expert_num_tokens,
111 const int64_t num_local_experts, const int64_t padded_m, const int64_t n,
112 const int64_t k);
113 #endif
114
115 void cutlass_scaled_mm_azp_sm75(
116 torch::stable::Tensor& c, torch::stable::Tensor const& a,
117 torch::stable::Tensor const& b, torch::stable::Tensor const& a_scales,
118 torch::stable::Tensor const& b_scales, torch::stable::Tensor const& azp_adj,
119 std::optional<torch::stable::Tensor> const& azp,
120 std::optional<torch::stable::Tensor> const& bias);
121
122 void cutlass_scaled_mm_azp_sm80(
123 torch::stable::Tensor& c, torch::stable::Tensor const& a,
124 torch::stable::Tensor const& b, torch::stable::Tensor const& a_scales,
125 torch::stable::Tensor const& b_scales, torch::stable::Tensor const& azp_adj,
126 std::optional<torch::stable::Tensor> const& azp,
127 std::optional<torch::stable::Tensor> const& bias);
128
129 void cutlass_scaled_mm_azp_sm89(
130 torch::stable::Tensor& c, torch::stable::Tensor const& a,
131 torch::stable::Tensor const& b, torch::stable::Tensor const& a_scales,
132 torch::stable::Tensor const& b_scales, torch::stable::Tensor const& azp_adj,
133 std::optional<torch::stable::Tensor> const& azp,
134 std::optional<torch::stable::Tensor> const& bias);
135
136 #if defined ENABLE_SCALED_MM_SM90 && ENABLE_SCALED_MM_SM90
137 void cutlass_scaled_mm_azp_sm90(
138 torch::stable::Tensor& c, torch::stable::Tensor const& a,
139 torch::stable::Tensor const& b, torch::stable::Tensor const& a_scales,
140 torch::stable::Tensor const& b_scales, torch::stable::Tensor const& azp_adj,
141 std::optional<torch::stable::Tensor> const& azp,
142 std::optional<torch::stable::Tensor> const& bias);
143 #endif
144
145 bool cutlass_scaled_mm_supports_fp8(int64_t cuda_device_capability) {
146 // CUTLASS FP8 kernels need at least
147 // CUDA 12.0 on SM90 systems (Hopper)
148 // CUDA 12.4 on SM89 systems (Lovelace)
149
150 #if defined CUDA_VERSION
151 if (cuda_device_capability >= 90) {
152 return CUDA_VERSION >= 12000;
153 } else if (cuda_device_capability >= 89) {
154 return CUDA_VERSION >= 12040;
155 }
156 #endif
157
158 return false;
159 }
160
161 bool cutlass_scaled_mm_supports_block_fp8(int64_t cuda_device_capability) {
162 // CUTLASS block-quantized FP8 kernels need at least CUDA 12.0
163 // and at least SM90 (Hopper)
164
165 #if defined CUDA_VERSION
166 if (cuda_device_capability >= 100) {
167 return CUDA_VERSION >= 12080;
168 } else if (cuda_device_capability >= 90) {
169 return CUDA_VERSION >= 12000;
170 }
171 #endif
172
173 return false;
174 }
175
176 bool cutlass_group_gemm_supported(int64_t cuda_device_capability) {
177 // CUTLASS grouped FP8 kernels need at least CUDA 12.3 and SM90 (Hopper)
178 // or CUDA 12.8 and SM100 (Blackwell). Only report archs that have an
179 // actual cutlass_moe_mm dispatch compiled into this file.
180
181 #if defined CUDA_VERSION
182 #if defined ENABLE_CUTLASS_MOE_SM100 && ENABLE_CUTLASS_MOE_SM100
183 if (cuda_device_capability >= 100 && cuda_device_capability < 120) {
184 return CUDA_VERSION >= 12080;
185 }
186 #endif
187 #if defined ENABLE_CUTLASS_MOE_SM90 && ENABLE_CUTLASS_MOE_SM90
188 if (cuda_device_capability >= 90 && cuda_device_capability < 100) {
189 return CUDA_VERSION >= 12030;
190 }
191 #endif
192 #endif
193
194 return false;
195 }
196
197 void cutlass_scaled_mm(torch::stable::Tensor& c, torch::stable::Tensor const& a,
198 torch::stable::Tensor const& b,
199 torch::stable::Tensor const& a_scales,
200 torch::stable::Tensor const& b_scales,
201 std::optional<torch::stable::Tensor> const& bias) {
202 // Checks for conformality
203 STD_TORCH_CHECK(a.dim() == 2 && b.dim() == 2 && c.dim() == 2);
204 STD_TORCH_CHECK(c.size(0) == a.size(0) && a.size(1) == b.size(0) &&
205 b.size(1) == c.size(1));
206
207 // Check for strides and alignment
208 STD_TORCH_CHECK(a.stride(1) == 1 && c.stride(1) == 1); // Row-major
209 STD_TORCH_CHECK(b.stride(0) == 1); // Column-major
210 STD_TORCH_CHECK(c.stride(0) % 16 == 0 &&
211 b.stride(1) % 16 == 0); // 16 Byte Alignment
212
213 if (bias) {
214 STD_TORCH_CHECK(bias->numel() == b.size(1) && bias->is_contiguous() &&
215 bias->dim() == 1);
216 }
217
218 const torch::stable::accelerator::DeviceGuard device_guard(
219 a.get_device_index());
220 int32_t version_num = get_sm_version_num();
221
222 #if defined ENABLE_SCALED_MM_SM120 && ENABLE_SCALED_MM_SM120
223 if (version_num >= 120) {
224 cutlass_scaled_mm_sm120(c, a, b, a_scales, b_scales, bias);
225 return;
226 }
227 #endif
228
229 #if defined ENABLE_SCALED_MM_SM100 && ENABLE_SCALED_MM_SM100
230 if (version_num >= 100 && version_num < 120) {
231 cutlass_scaled_mm_sm100(c, a, b, a_scales, b_scales, bias);
232 return;
233 }
234 #endif
235
236 // Guard against compilation issues for sm90 kernels
237 #if defined ENABLE_SCALED_MM_SM90 && ENABLE_SCALED_MM_SM90
238 if (version_num >= 90 && version_num < 100) {
239 // Hopper
240 cutlass_scaled_mm_sm90(c, a, b, a_scales, b_scales, bias);
241 return;
242 }
243 #endif
244
245 #if defined ENABLE_SCALED_MM_C2X && ENABLE_SCALED_MM_C2X
246 if (version_num == 89) {
247 // Ada Lovelace
248 cutlass_scaled_mm_sm89(c, a, b, a_scales, b_scales, bias);
249 return;
250 }
251
252 if (version_num >= 80) {
253 // Ampere
254 cutlass_scaled_mm_sm80(c, a, b, a_scales, b_scales, bias);
255 return;
256 }
257
258 if (version_num >= 75) {
259 // Turing
260 cutlass_scaled_mm_sm75(c, a, b, a_scales, b_scales, bias);
261 return;
262 }
263 #endif
264
265 STD_TORCH_CHECK_NOT_IMPLEMENTED(
266 false,
267 "No compiled cutlass_scaled_mm for a compute capability less than "
268 "CUDA device capability: ",
269 version_num);
270 }
271
272 void cutlass_moe_mm(torch::stable::Tensor& out_tensors,
273 torch::stable::Tensor const& a_tensors,
274 torch::stable::Tensor const& b_tensors,
275 torch::stable::Tensor const& a_scales,
276 torch::stable::Tensor const& b_scales,
277 torch::stable::Tensor const& expert_offsets,
278 torch::stable::Tensor const& problem_sizes,
279 torch::stable::Tensor const& a_strides,
280 torch::stable::Tensor const& b_strides,
281 torch::stable::Tensor const& c_strides, bool per_act_token,
282 bool per_out_ch) {
283 int32_t version_num = get_sm_version_num();
284 #if defined ENABLE_CUTLASS_MOE_SM100 && ENABLE_CUTLASS_MOE_SM100
285 if (version_num >= 100 && version_num < 110) {
286 cutlass_moe_mm_sm100(out_tensors, a_tensors, b_tensors, a_scales, b_scales,
287 expert_offsets, problem_sizes, a_strides, b_strides,
288 c_strides, per_act_token, per_out_ch);
289 return;
290 }
291 #endif
292 #if defined ENABLE_CUTLASS_MOE_SM90 && ENABLE_CUTLASS_MOE_SM90
293 if (version_num >= 90 && version_num < 100) {
294 cutlass_moe_mm_sm90(out_tensors, a_tensors, b_tensors, a_scales, b_scales,
295 expert_offsets, problem_sizes, a_strides, b_strides,
296 c_strides, per_act_token, per_out_ch);
297 return;
298 }
299 #endif
300 STD_TORCH_CHECK_NOT_IMPLEMENTED(
301 false,
302 "No compiled cutlass_scaled_mm for CUDA device capability: ", version_num,
303 ". Required capability: 90 or 100");
304 }
305
306 void get_cutlass_moe_mm_data(
307 const torch::stable::Tensor& topk_ids,
308 torch::stable::Tensor& expert_offsets,
309 torch::stable::Tensor& problem_sizes1,
310 torch::stable::Tensor& problem_sizes2,
311 torch::stable::Tensor& input_permutation,
312 torch::stable::Tensor& output_permutation, const int64_t num_experts,
313 const int64_t n, const int64_t k,
314 const std::optional<torch::stable::Tensor>& blockscale_offsets,
315 const bool is_gated) {
316 // This function currently gets compiled only if we have a valid cutlass moe
317 // mm to run it for.
318 int32_t version_num = get_sm_version_num();
319 #if (defined ENABLE_CUTLASS_MOE_SM90 && ENABLE_CUTLASS_MOE_SM90) || \
320 (defined ENABLE_CUTLASS_MOE_SM100 && ENABLE_CUTLASS_MOE_SM100) || \
321 (defined ENABLE_CUTLASS_MOE_SM120 && ENABLE_CUTLASS_MOE_SM120)
322 get_cutlass_moe_mm_data_caller(topk_ids, expert_offsets, problem_sizes1,
323 problem_sizes2, input_permutation,
324 output_permutation, num_experts, n, k,
325 blockscale_offsets, is_gated);
326 return;
327 #endif
328 STD_TORCH_CHECK_NOT_IMPLEMENTED(
329 false,
330 "No compiled get_cutlass_moe_mm_data: no cutlass_scaled_mm kernel for "
331 "CUDA device capability: ",
332 version_num, ". Required capability: 90, 100, or 120");
333 }
334
335 void get_cutlass_moe_mm_problem_sizes_from_expert_offsets(
336 const torch::stable::Tensor& expert_first_token_offset,
337 torch::stable::Tensor& problem_sizes1,
338 torch::stable::Tensor& problem_sizes2, const int64_t n, const int64_t k,
339 const bool swap_ab) {
340 int32_t version_num = get_sm_version_num();
341 #if (defined ENABLE_CUTLASS_MOE_SM90 && ENABLE_CUTLASS_MOE_SM90) || \
342 (defined ENABLE_CUTLASS_MOE_SM100 && ENABLE_CUTLASS_MOE_SM100) || \
343 (defined ENABLE_CUTLASS_MOE_SM120 && ENABLE_CUTLASS_MOE_SM120)
344 get_cutlass_moe_mm_problem_sizes_from_expert_offsets_caller(
345 expert_first_token_offset, problem_sizes1, problem_sizes2, n, k, swap_ab);
346 return;
347 #endif
348 STD_TORCH_CHECK_NOT_IMPLEMENTED(
349 false,
350 "No compiled get_cutlass_moe_mm_problem_sizes_from_expert_offsets: "
351 "no cutlass_scaled_mm kernel for CUDA device capability: ",
352 version_num, ". Required capability: 90, 100, or 120");
353 }
354
355 void get_cutlass_batched_moe_mm_data(
356 torch::stable::Tensor& expert_offsets,
357 torch::stable::Tensor& problem_sizes1,
358 torch::stable::Tensor& problem_sizes2,
359 const torch::stable::Tensor& expert_num_tokens,
360 const int64_t num_local_experts, const int64_t padded_m, const int64_t n,
361 const int64_t k) {
362 // This function currently gets compiled only if we have a valid cutlass moe
363 // mm to run it for.
364 int32_t version_num = get_sm_version_num();
365 #if (defined ENABLE_CUTLASS_MOE_SM90 && ENABLE_CUTLASS_MOE_SM90) || \
366 (defined ENABLE_CUTLASS_MOE_SM100 && ENABLE_CUTLASS_MOE_SM100) || \
367 (defined ENABLE_CUTLASS_MOE_SM120 && ENABLE_CUTLASS_MOE_SM120)
368 get_cutlass_batched_moe_mm_data_caller(expert_offsets, problem_sizes1,
369 problem_sizes2, expert_num_tokens,
370 num_local_experts, padded_m, n, k);
371 return;
372 #endif
373 STD_TORCH_CHECK_NOT_IMPLEMENTED(
374 false,
375 "No compiled get_cutlass_batched_moe_mm_data: no "
376 "cutlass_scaled_mm kernel "
377 "for CUDA device capability: ",
378 version_num, ". Required capability: 90, 100, or 120");
379 }
380
381 void cutlass_scaled_mm_azp(torch::stable::Tensor& c,
382 torch::stable::Tensor const& a,
383 torch::stable::Tensor const& b,
384 torch::stable::Tensor const& a_scales,
385 torch::stable::Tensor const& b_scales,
386 torch::stable::Tensor const& azp_adj,
387 std::optional<torch::stable::Tensor> const& azp,
388 std::optional<torch::stable::Tensor> const& bias) {
389 // Checks for conformality
390 STD_TORCH_CHECK(a.dim() == 2 && b.dim() == 2 && c.dim() == 2);
391 STD_TORCH_CHECK(c.size(0) == a.size(0) && a.size(1) == b.size(0) &&
392 b.size(1) == c.size(1));
393 STD_TORCH_CHECK(a_scales.numel() == 1 || a_scales.numel() == a.size(0));
394 STD_TORCH_CHECK(b_scales.numel() == 1 || b_scales.numel() == b.size(1));
395
396 // Check for strides and alignment
397 STD_TORCH_CHECK(a.stride(1) == 1 && c.stride(1) == 1); // Row-major
398 STD_TORCH_CHECK(b.stride(0) == 1); // Column-major
399 STD_TORCH_CHECK(c.stride(0) % 16 == 0 &&
400 b.stride(1) % 16 == 0); // 16 Byte Alignment
401 STD_TORCH_CHECK(a_scales.is_contiguous() && b_scales.is_contiguous());
402
403 // bias, azp, azp_adj are all 1d
404 // bias and azp_adj have n elements, azp has m elements
405 if (bias) {
406 STD_TORCH_CHECK(bias->numel() == b.size(1) && bias->is_contiguous());
407 }
408 if (azp) {
409 STD_TORCH_CHECK(azp->numel() == a.size(0) && azp->is_contiguous());
410 }
411 STD_TORCH_CHECK(azp_adj.numel() == b.size(1) && azp_adj.is_contiguous());
412
413 // azp & bias types
414 STD_TORCH_CHECK(azp_adj.scalar_type() == torch::headeronly::ScalarType::Int);
415 STD_TORCH_CHECK(!azp ||
416 azp->scalar_type() == torch::headeronly::ScalarType::Int);
417 STD_TORCH_CHECK(!bias || bias->scalar_type() == c.scalar_type(),
418 "currently bias dtype must match output dtype ",
419 c.scalar_type());
420
421 const torch::stable::accelerator::DeviceGuard device_guard(
422 a.get_device_index());
423
424 int32_t version_num = get_sm_version_num();
425
426 #if defined ENABLE_SCALED_MM_SM90 && ENABLE_SCALED_MM_SM90
427 if (version_num >= 90) {
428 cutlass_scaled_mm_azp_sm90(c, a, b, a_scales, b_scales, azp_adj, azp, bias);
429 return;
430 }
431 #endif
432
433 #if defined ENABLE_SCALED_MM_C2X && ENABLE_SCALED_MM_C2X
434 if (version_num == 89) {
435 // Ada Lovelace
436 cutlass_scaled_mm_azp_sm89(c, a, b, a_scales, b_scales, azp_adj, azp, bias);
437 return;
438 }
439
440 if (version_num >= 80) {
441 // Ampere
442 cutlass_scaled_mm_azp_sm80(c, a, b, a_scales, b_scales, azp_adj, azp, bias);
443 return;
444 }
445
446 // Turing
447 STD_TORCH_CHECK(version_num >= 75);
448 cutlass_scaled_mm_azp_sm75(c, a, b, a_scales, b_scales, azp_adj, azp, bias);
449 return;
450 #endif
451
452 STD_TORCH_CHECK_NOT_IMPLEMENTED(
453 false,
454 "No compiled cutlass_scaled_mm_azp for a compute capability less than "
455 "CUDA device capability: ",
456 version_num);
457 }