main
cu 229 lines 10.2 KB
Raw
1 #include <stddef.h>
2 #include <torch/csrc/stable/tensor.h>
3 #include <torch/headeronly/core/ScalarType.h>
4 #include "cutlass/cutlass.h"
5
6 #include "scaled_mm_c2x.cuh"
7 #include "scaled_mm_c2x_sm75_dispatch.cuh"
8 #include "scaled_mm_c2x_sm80_dispatch.cuh"
9 #include "scaled_mm_c2x_sm89_fp8_dispatch.cuh"
10 #include "scaled_mm_c2x_sm89_int8_dispatch.cuh"
11
12 #include "core/batch_invariant.hpp"
13 #include "libtorch_stable/cutlass_extensions/epilogue/scaled_mm_epilogues_c2x.hpp"
14
15 using namespace vllm;
16
17 /*
18 This file defines quantized GEMM operations using the CUTLASS 2.x API, for
19 NVIDIA GPUs with SM versions prior to sm90 (Hopper).
20 */
21
22 template <template <typename, typename> typename Epilogue,
23 typename... EpilogueArgs>
24 void cutlass_scaled_mm_sm75_epilogue(torch::stable::Tensor& out,
25 torch::stable::Tensor const& a,
26 torch::stable::Tensor const& b,
27 EpilogueArgs&&... epilogue_args) {
28 STD_TORCH_CHECK(a.scalar_type() == torch::headeronly::ScalarType::Char);
29 STD_TORCH_CHECK(b.scalar_type() == torch::headeronly::ScalarType::Char);
30
31 if (out.scalar_type() == torch::headeronly::ScalarType::BFloat16) {
32 return cutlass_gemm_sm75_dispatch<int8_t, cutlass::bfloat16_t, Epilogue>(
33 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
34 } else {
35 STD_TORCH_CHECK(out.scalar_type() == torch::headeronly::ScalarType::Half);
36 return cutlass_gemm_sm75_dispatch<int8_t, cutlass::half_t, Epilogue>(
37 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
38 }
39 }
40
41 void cutlass_scaled_mm_sm75(torch::stable::Tensor& out,
42 torch::stable::Tensor const& a,
43 torch::stable::Tensor const& b,
44 torch::stable::Tensor const& a_scales,
45 torch::stable::Tensor const& b_scales,
46 std::optional<torch::stable::Tensor> const& bias) {
47 STD_TORCH_CHECK(a_scales.scalar_type() ==
48 torch::headeronly::ScalarType::Float);
49 STD_TORCH_CHECK(b_scales.scalar_type() ==
50 torch::headeronly::ScalarType::Float);
51 if (bias) {
52 STD_TORCH_CHECK(bias->scalar_type() == out.scalar_type(),
53 "currently bias dtype must match output dtype ",
54 out.scalar_type());
55 return cutlass_scaled_mm_sm75_epilogue<c2x::ScaledEpilogueBias>(
56 out, a, b, a_scales, b_scales, *bias);
57 } else {
58 return cutlass_scaled_mm_sm75_epilogue<c2x::ScaledEpilogue>(
59 out, a, b, a_scales, b_scales);
60 }
61 }
62
63 void cutlass_scaled_mm_azp_sm75(
64 torch::stable::Tensor& out, torch::stable::Tensor const& a,
65 torch::stable::Tensor const& b, torch::stable::Tensor const& a_scales,
66 torch::stable::Tensor const& b_scales, torch::stable::Tensor const& azp_adj,
67 std::optional<torch::stable::Tensor> const& azp,
68 std::optional<torch::stable::Tensor> const& bias) {
69 STD_TORCH_CHECK(a_scales.scalar_type() ==
70 torch::headeronly::ScalarType::Float);
71 STD_TORCH_CHECK(b_scales.scalar_type() ==
72 torch::headeronly::ScalarType::Float);
73
74 if (azp) {
75 return cutlass_scaled_mm_sm75_epilogue<c2x::ScaledEpilogueBiasAzpToken>(
76 out, a, b, a_scales, b_scales, azp_adj, *azp, bias);
77 } else {
78 return cutlass_scaled_mm_sm75_epilogue<c2x::ScaledEpilogueBiasAzp>(
79 out, a, b, a_scales, b_scales, azp_adj, bias);
80 }
81 }
82
83 template <template <typename, typename> typename Epilogue,
84 typename... EpilogueArgs>
85 void cutlass_scaled_mm_sm80_epilogue(torch::stable::Tensor& out,
86 torch::stable::Tensor const& a,
87 torch::stable::Tensor const& b,
88 EpilogueArgs&&... epilogue_args) {
89 STD_TORCH_CHECK(a.scalar_type() == torch::headeronly::ScalarType::Char);
90 STD_TORCH_CHECK(b.scalar_type() == torch::headeronly::ScalarType::Char);
91
92 if (out.scalar_type() == torch::headeronly::ScalarType::BFloat16) {
93 return cutlass_gemm_sm80_dispatch<int8_t, cutlass::bfloat16_t, Epilogue>(
94 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
95 } else {
96 STD_TORCH_CHECK(out.scalar_type() == torch::headeronly::ScalarType::Half);
97 return cutlass_gemm_sm80_dispatch<int8_t, cutlass::half_t, Epilogue>(
98 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
99 }
100 }
101
102 void cutlass_scaled_mm_sm80(torch::stable::Tensor& out,
103 torch::stable::Tensor const& a,
104 torch::stable::Tensor const& b,
105 torch::stable::Tensor const& a_scales,
106 torch::stable::Tensor const& b_scales,
107 std::optional<torch::stable::Tensor> const& bias) {
108 STD_TORCH_CHECK(a_scales.scalar_type() ==
109 torch::headeronly::ScalarType::Float);
110 STD_TORCH_CHECK(b_scales.scalar_type() ==
111 torch::headeronly::ScalarType::Float);
112 if (bias) {
113 STD_TORCH_CHECK(bias->scalar_type() == out.scalar_type(),
114 "currently bias dtype must match output dtype ",
115 out.scalar_type());
116 return cutlass_scaled_mm_sm80_epilogue<c2x::ScaledEpilogueBias>(
117 out, a, b, a_scales, b_scales, *bias);
118 } else {
119 return cutlass_scaled_mm_sm80_epilogue<c2x::ScaledEpilogue>(
120 out, a, b, a_scales, b_scales);
121 }
122 }
123
124 void cutlass_scaled_mm_azp_sm80(
125 torch::stable::Tensor& out, torch::stable::Tensor const& a,
126 torch::stable::Tensor const& b, torch::stable::Tensor const& a_scales,
127 torch::stable::Tensor const& b_scales, torch::stable::Tensor const& azp_adj,
128 std::optional<torch::stable::Tensor> const& azp,
129 std::optional<torch::stable::Tensor> const& bias) {
130 STD_TORCH_CHECK(a_scales.scalar_type() ==
131 torch::headeronly::ScalarType::Float);
132 STD_TORCH_CHECK(b_scales.scalar_type() ==
133 torch::headeronly::ScalarType::Float);
134
135 if (azp) {
136 return cutlass_scaled_mm_sm80_epilogue<c2x::ScaledEpilogueBiasAzpToken>(
137 out, a, b, a_scales, b_scales, azp_adj, *azp, bias);
138 } else {
139 return cutlass_scaled_mm_sm80_epilogue<c2x::ScaledEpilogueBiasAzp>(
140 out, a, b, a_scales, b_scales, azp_adj, bias);
141 }
142 }
143
144 template <template <typename, typename> typename Epilogue,
145 typename... EpilogueArgs>
146 void cutlass_scaled_mm_sm89_epilogue(torch::stable::Tensor& out,
147 torch::stable::Tensor const& a,
148 torch::stable::Tensor const& b,
149 EpilogueArgs&&... epilogue_args) {
150 if (a.scalar_type() == torch::headeronly::ScalarType::Char) {
151 STD_TORCH_CHECK(b.scalar_type() == torch::headeronly::ScalarType::Char);
152
153 if (out.scalar_type() == torch::headeronly::ScalarType::BFloat16) {
154 return cutlass_gemm_sm89_int8_dispatch<int8_t, cutlass::bfloat16_t,
155 Epilogue>(
156 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
157 } else {
158 assert(out.scalar_type() == torch::headeronly::ScalarType::Half);
159 return cutlass_gemm_sm89_int8_dispatch<int8_t, cutlass::half_t, Epilogue>(
160 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
161 }
162 } else {
163 STD_TORCH_CHECK(a.scalar_type() ==
164 torch::headeronly::ScalarType::Float8_e4m3fn);
165 STD_TORCH_CHECK(b.scalar_type() ==
166 torch::headeronly::ScalarType::Float8_e4m3fn);
167
168 if (out.scalar_type() == torch::headeronly::ScalarType::BFloat16) {
169 return cutlass_gemm_sm89_fp8_dispatch<cutlass::float_e4m3_t,
170 cutlass::bfloat16_t, Epilogue>(
171 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
172 } else {
173 STD_TORCH_CHECK(out.scalar_type() == torch::headeronly::ScalarType::Half);
174 return cutlass_gemm_sm89_fp8_dispatch<cutlass::float_e4m3_t,
175 cutlass::half_t, Epilogue>(
176 out, a, b, std::forward<EpilogueArgs>(epilogue_args)...);
177 }
178 }
179 }
180
181 void cutlass_scaled_mm_sm89(torch::stable::Tensor& out,
182 torch::stable::Tensor const& a,
183 torch::stable::Tensor const& b,
184 torch::stable::Tensor const& a_scales,
185 torch::stable::Tensor const& b_scales,
186 std::optional<torch::stable::Tensor> const& bias) {
187 STD_TORCH_CHECK(a_scales.scalar_type() ==
188 torch::headeronly::ScalarType::Float);
189 STD_TORCH_CHECK(b_scales.scalar_type() ==
190 torch::headeronly::ScalarType::Float);
191 if (bias) {
192 STD_TORCH_CHECK(bias->scalar_type() == out.scalar_type(),
193 "currently bias dtype must match output dtype ",
194 out.scalar_type());
195 if (vllm_is_batch_invariant()) {
196 return cutlass_scaled_mm_sm89_fp8_batch_invariant_epilogue<
197 c2x::ScaledEpilogueBias>(out, a, b, a_scales, b_scales, *bias);
198 }
199 return cutlass_scaled_mm_sm89_epilogue<c2x::ScaledEpilogueBias>(
200 out, a, b, a_scales, b_scales, *bias);
201 } else {
202 if (vllm_is_batch_invariant()) {
203 return cutlass_scaled_mm_sm89_fp8_batch_invariant_epilogue<
204 c2x::ScaledEpilogue>(out, a, b, a_scales, b_scales);
205 }
206 return cutlass_scaled_mm_sm89_epilogue<c2x::ScaledEpilogue>(
207 out, a, b, a_scales, b_scales);
208 }
209 }
210
211 void cutlass_scaled_mm_azp_sm89(
212 torch::stable::Tensor& out, torch::stable::Tensor const& a,
213 torch::stable::Tensor const& b, torch::stable::Tensor const& a_scales,
214 torch::stable::Tensor const& b_scales, torch::stable::Tensor const& azp_adj,
215 std::optional<torch::stable::Tensor> const& azp,
216 std::optional<torch::stable::Tensor> const& bias) {
217 STD_TORCH_CHECK(a_scales.scalar_type() ==
218 torch::headeronly::ScalarType::Float);
219 STD_TORCH_CHECK(b_scales.scalar_type() ==
220 torch::headeronly::ScalarType::Float);
221
222 if (azp) {
223 return cutlass_scaled_mm_sm89_epilogue<c2x::ScaledEpilogueBiasAzpToken>(
224 out, a, b, a_scales, b_scales, azp_adj, *azp, bias);
225 } else {
226 return cutlass_scaled_mm_sm89_epilogue<c2x::ScaledEpilogueBiasAzp>(
227 out, a, b, a_scales, b_scales, azp_adj, bias);
228 }
229 }