main
h 269 lines 12.5 KB
Raw
1
2 #include "marlin_dtypes.cuh"
3
4 namespace MARLIN_NAMESPACE_NAME {
5
6 // m16n8k16 tensor core mma instruction with fp16 inputs and fp32
7 // output/accumulation.
8 template <vllm::ScalarTypeId type_id, bool use_fp16_accum, int k_size = 16>
9 __device__ inline void mma(
10 const typename MarlinScalarType<type_id>::FragA& a_frag,
11 const typename MarlinScalarType<type_id>::FragB& frag_b,
12 typename MarlinScalarType<type_id>::FragC& frag_c, int idx = 0) {
13 const uint32_t* a = reinterpret_cast<const uint32_t*>(&a_frag);
14 const uint32_t* b = reinterpret_cast<const uint32_t*>(&frag_b);
15 using scalar_t = typename MarlinScalarType<type_id>::scalar_t;
16 if constexpr (!std::is_same<scalar_t, half>::value || k_size != 16) {
17 static_assert(!use_fp16_accum);
18 }
19
20 if constexpr (k_size == 16) {
21 if constexpr (std::is_same<scalar_t, half>::value && !use_fp16_accum) {
22 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == 750
23 float* c = reinterpret_cast<float*>(&frag_c);
24 asm volatile(
25 "mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 "
26 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
27 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
28 : "r"(a[0]), "r"(a[1]), "r"(b[0]), "f"(c[0]), "f"(c[1]), "f"(c[2]),
29 "f"(c[3]));
30 asm volatile(
31 "mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 "
32 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
33 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
34 : "r"(a[2]), "r"(a[3]), "r"(b[1]), "f"(c[0]), "f"(c[1]), "f"(c[2]),
35 "f"(c[3]));
36 #else
37 float* c = reinterpret_cast<float*>(&frag_c);
38 asm volatile(
39 "mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 "
40 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
41 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
42 : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]),
43 "f"(c[0]), "f"(c[1]), "f"(c[2]), "f"(c[3]));
44 #endif
45 } else if constexpr (std::is_same<scalar_t, half>::value &&
46 use_fp16_accum) {
47 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == 750
48 uint32_t* c = reinterpret_cast<uint32_t*>(&frag_c);
49 asm volatile(
50 "mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 "
51 "{%0,%1}, {%2,%3}, {%4}, {%5,%6};\n"
52 : "=r"(c[0]), "=r"(c[1])
53 : "r"(a[0]), "r"(a[1]), "r"(b[0]), "r"(c[0]), "r"(c[1]));
54 asm volatile(
55 "mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 "
56 "{%0,%1}, {%2,%3}, {%4}, {%5,%6};\n"
57 : "=r"(c[0]), "=r"(c[1])
58 : "r"(a[2]), "r"(a[3]), "r"(b[1]), "r"(c[0]), "r"(c[1]));
59 #else
60 uint32_t* c = reinterpret_cast<uint32_t*>(&frag_c);
61 asm volatile(
62 "mma.sync.aligned.m16n8k16.row.col.f16.f16.f16.f16 "
63 "{%0,%1}, {%2,%3,%4,%5}, {%6,%7}, {%8,%9};\n"
64 : "=r"(c[0]), "=r"(c[1])
65 : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]),
66 "r"(c[0]), "r"(c[1]));
67 #endif
68 } else if constexpr (std::is_same<scalar_t, nv_bfloat16>::value) {
69 float* c = reinterpret_cast<float*>(&frag_c);
70 asm volatile(
71 "mma.sync.aligned.m16n8k16.row.col.f32.bf16.bf16.f32 "
72 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
73 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
74 : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]),
75 "f"(c[0]), "f"(c[1]), "f"(c[2]), "f"(c[3]));
76 } else if constexpr (std::is_same<scalar_t, __nv_fp8_e4m3>::value) {
77 float* c = reinterpret_cast<float*>(&frag_c);
78 asm volatile(
79 "mma.sync.aligned.m16n8k16.row.col.f32.e4m3.e4m3.f32 "
80 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
81 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
82 : "r"(a[idx * 2]), "r"(a[idx * 2 + 1]), "r"(b[idx]), "f"(c[0]),
83 "f"(c[1]), "f"(c[2]), "f"(c[3]));
84 } else if constexpr (std::is_same<scalar_t, int8_t>::value) {
85 int32_t* c = reinterpret_cast<int32_t*>(&frag_c);
86 asm volatile(
87 "mma.sync.aligned.m16n8k16.row.col.s32.s8.s8.s32.satfinite "
88 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
89 : "=r"(c[0]), "=r"(c[1]), "=r"(c[2]), "=r"(c[3])
90 : "r"(a[idx * 2]), "r"(a[idx * 2 + 1]), "r"(b[idx]), "r"(c[0]),
91 "r"(c[1]), "r"(c[2]), "r"(c[3]));
92 }
93 } else if (k_size == 32) {
94 if constexpr (std::is_same<scalar_t, __nv_fp8_e4m3>::value) {
95 float* c = reinterpret_cast<float*>(&frag_c);
96 asm volatile(
97 "mma.sync.aligned.m16n8k32.row.col.f32.e4m3.e4m3.f32 "
98 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
99 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
100 : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]),
101 "f"(c[0]), "f"(c[1]), "f"(c[2]), "f"(c[3]));
102 } else if constexpr (std::is_same<scalar_t, int8_t>::value) {
103 int32_t* c = reinterpret_cast<int32_t*>(&frag_c);
104 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == 750
105 asm volatile(
106 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
107 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
108 : "=r"(c[0]), "=r"(c[1])
109 : "r"(a[0]), "r"(b[0]), "r"(c[0]), "r"(c[1]));
110 asm volatile(
111 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
112 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
113 : "=r"(c[2]), "=r"(c[3])
114 : "r"(a[1]), "r"(b[0]), "r"(c[2]), "r"(c[3]));
115 asm volatile(
116 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
117 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
118 : "=r"(c[0]), "=r"(c[1])
119 : "r"(a[2]), "r"(b[1]), "r"(c[0]), "r"(c[1]));
120 asm volatile(
121 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
122 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
123 : "=r"(c[2]), "=r"(c[3])
124 : "r"(a[3]), "r"(b[1]), "r"(c[2]), "r"(c[3]));
125 #else
126 asm volatile(
127 "mma.sync.aligned.m16n8k32.row.col.s32.s8.s8.s32.satfinite "
128 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
129 : "=r"(c[0]), "=r"(c[1]), "=r"(c[2]), "=r"(c[3])
130 : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]),
131 "r"(c[0]), "r"(c[1]), "r"(c[2]), "r"(c[3]));
132 #endif
133 }
134 }
135 }
136
137 template <vllm::ScalarTypeId type_id, bool use_fp16_accum, int k_size = 16>
138 __device__ inline void mma_trans(
139 const typename MarlinScalarType<type_id>::FragA& a_frag,
140 const typename MarlinScalarType<type_id>::FragB& frag_b,
141 const typename MarlinScalarType<type_id>::FragB& frag_b2,
142 typename MarlinScalarType<type_id>::FragC& frag_c) {
143 const uint32_t* a = reinterpret_cast<const uint32_t*>(&a_frag);
144 const uint32_t* b = reinterpret_cast<const uint32_t*>(&frag_b);
145 const uint32_t* b2 = reinterpret_cast<const uint32_t*>(&frag_b2);
146 float* c = reinterpret_cast<float*>(&frag_c);
147 using scalar_t = typename MarlinScalarType<type_id>::scalar_t;
148 if constexpr (!std::is_same<scalar_t, half>::value || k_size != 16) {
149 static_assert(!use_fp16_accum);
150 }
151
152 if constexpr (k_size == 16) {
153 if constexpr (std::is_same<scalar_t, half>::value && !use_fp16_accum) {
154 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == 750
155 float* c = reinterpret_cast<float*>(&frag_c);
156 asm volatile(
157 "mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 "
158 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
159 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
160 : "r"(b[0]), "r"(b2[0]), "r"(a[0]), "f"(c[0]), "f"(c[1]), "f"(c[2]),
161 "f"(c[3]));
162 asm volatile(
163 "mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 "
164 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
165 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
166 : "r"(b[1]), "r"(b2[1]), "r"(a[1]), "f"(c[0]), "f"(c[1]), "f"(c[2]),
167 "f"(c[3]));
168 #else
169 float* c = reinterpret_cast<float*>(&frag_c);
170 asm volatile(
171 "mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 "
172 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
173 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
174 : "r"(b[0]), "r"(b2[0]), "r"(b[1]), "r"(b2[1]), "r"(a[0]), "r"(a[1]),
175 "f"(c[0]), "f"(c[1]), "f"(c[2]), "f"(c[3]));
176 #endif
177 } else if constexpr (std::is_same<scalar_t, half>::value &&
178 use_fp16_accum) {
179 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == 750
180 uint32_t* c = reinterpret_cast<uint32_t*>(&frag_c);
181 asm volatile(
182 "mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 "
183 "{%0,%1}, {%2,%3}, {%4}, {%5,%6};\n"
184 : "=r"(c[0]), "=r"(c[1])
185 : "r"(b[0]), "r"(b2[0]), "r"(a[0]), "r"(c[0]), "r"(c[1]));
186 asm volatile(
187 "mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 "
188 "{%0,%1}, {%2,%3}, {%4}, {%5,%6};\n"
189 : "=r"(c[0]), "=r"(c[1])
190 : "r"(b[1]), "r"(b2[1]), "r"(a[1]), "r"(c[0]), "r"(c[1]));
191 #else
192 uint32_t* c = reinterpret_cast<uint32_t*>(&frag_c);
193 asm volatile(
194 "mma.sync.aligned.m16n8k16.row.col.f16.f16.f16.f16 "
195 "{%0,%1}, {%2,%3,%4,%5}, {%6,%7}, {%8,%9};\n"
196 : "=r"(c[0]), "=r"(c[1])
197 : "r"(b[0]), "r"(b2[0]), "r"(b[1]), "r"(b2[1]), "r"(a[0]), "r"(a[1]),
198 "r"(c[0]), "r"(c[1]));
199 #endif
200 } else if constexpr (std::is_same<scalar_t, nv_bfloat16>::value) {
201 float* c = reinterpret_cast<float*>(&frag_c);
202 asm volatile(
203 "mma.sync.aligned.m16n8k16.row.col.f32.bf16.bf16.f32 "
204 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
205 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
206 : "r"(b[0]), "r"(b2[0]), "r"(b[1]), "r"(b2[1]), "r"(a[0]), "r"(a[1]),
207 "f"(c[0]), "f"(c[1]), "f"(c[2]), "f"(c[3]));
208 } else if constexpr (std::is_same<scalar_t, __nv_fp8_e4m3>::value) {
209 float* c = reinterpret_cast<float*>(&frag_c);
210 asm volatile(
211 "mma.sync.aligned.m16n8k16.row.col.f32.e4m3.e4m3.f32 "
212 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
213 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
214 : "r"(b[0]), "r"(b2[0]), "r"(a[0]), "f"(c[0]), "f"(c[1]), "f"(c[2]),
215 "f"(c[3]));
216 } else if constexpr (std::is_same<scalar_t, int8_t>::value) {
217 int32_t* c = reinterpret_cast<int32_t*>(&frag_c);
218 asm volatile(
219 "mma.sync.aligned.m16n8k16.row.col.s32.s8.s8.s32.satfinite "
220 "{%0,%1,%2,%3}, {%4,%5}, {%6}, {%7,%8,%9,%10};\n"
221 : "=r"(c[0]), "=r"(c[1]), "=r"(c[2]), "=r"(c[3])
222 : "r"(b[0]), "r"(b2[0]), "r"(a[0]), "r"(c[0]), "r"(c[1]), "r"(c[2]),
223 "r"(c[3]));
224 }
225 } else {
226 if constexpr (std::is_same<scalar_t, __nv_fp8_e4m3>::value) {
227 float* c = reinterpret_cast<float*>(&frag_c);
228 asm volatile(
229 "mma.sync.aligned.m16n8k32.row.col.f32.e4m3.e4m3.f32 "
230 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
231 : "=f"(c[0]), "=f"(c[1]), "=f"(c[2]), "=f"(c[3])
232 : "r"(b[0]), "r"(b2[0]), "r"(b[1]), "r"(b2[1]), "r"(a[0]), "r"(a[1]),
233 "f"(c[0]), "f"(c[1]), "f"(c[2]), "f"(c[3]));
234 } else if constexpr (std::is_same<scalar_t, int8_t>::value) {
235 int32_t* c = reinterpret_cast<int32_t*>(&frag_c);
236 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == 750
237 asm volatile(
238 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
239 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
240 : "=r"(c[0]), "=r"(c[1])
241 : "r"(b[0]), "r"(a[0]), "r"(c[0]), "r"(c[1]));
242 asm volatile(
243 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
244 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
245 : "=r"(c[2]), "=r"(c[3])
246 : "r"(b2[1]), "r"(a[0]), "r"(c[2]), "r"(c[3]));
247 asm volatile(
248 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
249 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
250 : "=r"(c[0]), "=r"(c[1])
251 : "r"(b[0]), "r"(a[1]), "r"(c[0]), "r"(c[1]));
252 asm volatile(
253 "mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32.satfinite "
254 "{%0,%1}, {%2}, {%3}, {%4,%5};\n"
255 : "=r"(c[2]), "=r"(c[3])
256 : "r"(b2[1]), "r"(a[1]), "r"(c[2]), "r"(c[3]));
257 #else
258 asm volatile(
259 "mma.sync.aligned.m16n8k32.row.col.s32.s8.s8.s32.satfinite "
260 "{%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%11,%12,%13};\n"
261 : "=r"(c[0]), "=r"(c[1]), "=r"(c[2]), "=r"(c[3])
262 : "r"(b[0]), "r"(b2[0]), "r"(b[1]), "r"(b2[1]), "r"(a[0]), "r"(a[1]),
263 "r"(c[0]), "r"(c[1]), "r"(c[2]), "r"(c[3]));
264 #endif
265 }
266 }
267 }
268
269 } // namespace MARLIN_NAMESPACE_NAME