main
cuh 463 lines 12 KB
Raw
1 /*
2 * Adapted from
3 * https://github.com/NVIDIA/FasterTransformer/blob/release/v5.3_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention/decoder_masked_multihead_attention_template.hpp
4 * and
5 * https://github.com/NVIDIA/FasterTransformer/blob/release/v5.3_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention_utils.h
6 * Copyright (c) 2023, The vLLM team.
7 * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21 #pragma once
22
23 #include "attention_generic.cuh"
24 #include "dtype_float32.cuh"
25
26 #ifndef USE_ROCM
27 #include <cuda_bf16.h>
28 #include <cuda_fp16.h>
29 #else
30 #include <hip/hip_bf16.h>
31 #include <hip/hip_fp16.h>
32
33 typedef __hip_bfloat162 __nv_bfloat162;
34 typedef __hip_bfloat16 __nv_bfloat16;
35 #endif
36
37 #include <stdint.h>
38
39 namespace vllm {
40
41 // Define custom BF16 vector data types.
42 struct bf16_4_t {
43 __nv_bfloat162 x;
44 __nv_bfloat162 y;
45 };
46
47 struct bf16_8_t {
48 __nv_bfloat162 x;
49 __nv_bfloat162 y;
50 __nv_bfloat162 z;
51 __nv_bfloat162 w;
52 };
53
54 // BF16 vector types for Q, K, V.
55 template <>
56 struct Vec<__nv_bfloat16, 1> {
57 using Type = __nv_bfloat16;
58 };
59 template <>
60 struct Vec<__nv_bfloat16, 2> {
61 using Type = __nv_bfloat162;
62 };
63 template <>
64 struct Vec<__nv_bfloat16, 4> {
65 using Type = bf16_4_t;
66 };
67 template <>
68 struct Vec<__nv_bfloat16, 8> {
69 using Type = bf16_8_t;
70 };
71
72 // FP32 accumulator vector types corresponding to Vec.
73 template <>
74 struct FloatVec<__nv_bfloat16> {
75 using Type = float;
76 };
77 template <>
78 struct FloatVec<__nv_bfloat162> {
79 using Type = float2;
80 };
81 template <>
82 struct FloatVec<bf16_4_t> {
83 using Type = Float4_;
84 };
85 template <>
86 struct FloatVec<bf16_8_t> {
87 using Type = Float8_;
88 };
89
90 // Utility functions for type conversions.
91 inline __device__ float2 bf1622float2(const __nv_bfloat162 val) {
92 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
93 assert(false);
94 #else
95 return __bfloat1622float2(val);
96 #endif
97 __builtin_unreachable(); // Suppress missing return statement warning
98 }
99
100 inline __device__ __nv_bfloat162 bf162bf162(const __nv_bfloat16 val) {
101 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
102 assert(false);
103 #else
104 return __bfloat162bfloat162(val);
105 #endif
106 __builtin_unreachable(); // Suppress missing return statement warning
107 }
108
109 // Vector addition.
110 inline __device__ __nv_bfloat16 add(__nv_bfloat16 a, __nv_bfloat16 b) {
111 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
112 assert(false);
113 #else
114 #ifndef USE_ROCM
115 return a + b;
116 #else
117 return __hadd(a, b);
118 #endif
119 #endif
120 __builtin_unreachable(); // Suppress missing return statement warning
121 }
122
123 inline __device__ __nv_bfloat162 add(__nv_bfloat162 a, __nv_bfloat162 b) {
124 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
125 assert(false);
126 #else
127 return __hadd2(a, b);
128 #endif
129 __builtin_unreachable(); // Suppress missing return statement warning
130 }
131
132 inline __device__ bf16_4_t add(bf16_4_t a, bf16_4_t b) {
133 bf16_4_t c;
134 c.x = add(a.x, b.x);
135 c.y = add(a.y, b.y);
136 return c;
137 }
138
139 inline __device__ bf16_8_t add(bf16_8_t a, bf16_8_t b) {
140 bf16_8_t c;
141 c.x = add(a.x, b.x);
142 c.y = add(a.y, b.y);
143 c.z = add(a.z, b.z);
144 c.w = add(a.w, b.w);
145 return c;
146 }
147
148 inline __device__ float2 add(__nv_bfloat162 a, float2 fb) {
149 float2 fa = bf1622float2(a);
150 return add(fa, fb);
151 }
152
153 inline __device__ Float4_ add(bf16_4_t a, Float4_ fb) {
154 Float4_ fc;
155 fc.x = add(a.x, fb.x);
156 fc.y = add(a.y, fb.y);
157 return fc;
158 }
159
160 inline __device__ Float8_ add(bf16_8_t a, Float8_ fb) {
161 Float8_ fc;
162 fc.x = add(a.x, fb.x);
163 fc.y = add(a.y, fb.y);
164 fc.z = add(a.z, fb.z);
165 fc.w = add(a.w, fb.w);
166 return fc;
167 }
168
169 // Vector multiplication.
170 template <>
171 inline __device__ __nv_bfloat16 mul(__nv_bfloat16 a, __nv_bfloat16 b) {
172 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
173 assert(false);
174 #else
175 return __hmul(a, b);
176 #endif
177 __builtin_unreachable(); // Suppress missing return statement warning
178 }
179
180 template <>
181 inline __device__ __nv_bfloat162 mul(__nv_bfloat162 a, __nv_bfloat162 b) {
182 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
183 assert(false);
184 #else
185 return __hmul2(a, b);
186 #endif
187 __builtin_unreachable(); // Suppress missing return statement warning
188 }
189
190 template <>
191 inline __device__ __nv_bfloat162 mul(__nv_bfloat16 a, __nv_bfloat162 b) {
192 return mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(bf162bf162(a), b);
193 }
194
195 template <>
196 inline __device__ bf16_4_t mul(bf16_4_t a, bf16_4_t b) {
197 bf16_4_t c;
198 c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
199 c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
200 return c;
201 }
202
203 template <>
204 inline __device__ bf16_4_t mul(__nv_bfloat16 a, bf16_4_t b) {
205 __nv_bfloat162 s = bf162bf162(a);
206 bf16_4_t c;
207 c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.x);
208 c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.y);
209 return c;
210 }
211
212 template <>
213 inline __device__ bf16_8_t mul(bf16_8_t a, bf16_8_t b) {
214 bf16_8_t c;
215 c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
216 c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
217 c.z = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.z, b.z);
218 c.w = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.w, b.w);
219 return c;
220 }
221
222 template <>
223 inline __device__ bf16_8_t mul(__nv_bfloat16 a, bf16_8_t b) {
224 __nv_bfloat162 s = bf162bf162(a);
225 bf16_8_t c;
226 c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.x);
227 c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.y);
228 c.z = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.z);
229 c.w = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.w);
230 return c;
231 }
232
233 template <>
234 inline __device__ float mul(__nv_bfloat16 a, __nv_bfloat16 b) {
235 float fa = __bfloat162float(a);
236 float fb = __bfloat162float(b);
237 return fa * fb;
238 }
239
240 template <>
241 inline __device__ float2 mul(__nv_bfloat162 a, __nv_bfloat162 b) {
242 float2 fa = bf1622float2(a);
243 float2 fb = bf1622float2(b);
244 return mul<float2, float2, float2>(fa, fb);
245 }
246
247 template <>
248 inline __device__ float2 mul(__nv_bfloat16 a, __nv_bfloat162 b) {
249 return mul<float2, __nv_bfloat162, __nv_bfloat162>(bf162bf162(a), b);
250 }
251
252 template <>
253 inline __device__ Float4_ mul(bf16_4_t a, bf16_4_t b) {
254 Float4_ fc;
255 fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
256 fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
257 return fc;
258 }
259
260 template <>
261 inline __device__ Float4_ mul(__nv_bfloat16 a, bf16_4_t b) {
262 __nv_bfloat162 s = bf162bf162(a);
263 Float4_ fc;
264 fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.x);
265 fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.y);
266 return fc;
267 }
268
269 template <>
270 inline __device__ Float8_ mul(bf16_8_t a, bf16_8_t b) {
271 Float8_ fc;
272 fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
273 fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
274 fc.z = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.z, b.z);
275 fc.w = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.w, b.w);
276 return fc;
277 }
278
279 template <>
280 inline __device__ Float8_ mul(__nv_bfloat16 a, bf16_8_t b) {
281 __nv_bfloat162 s = bf162bf162(a);
282 Float8_ fc;
283 fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.x);
284 fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.y);
285 fc.z = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.z);
286 fc.w = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.w);
287 return fc;
288 }
289
290 // Vector fused multiply-add.
291 inline __device__ __nv_bfloat162 fma(__nv_bfloat162 a, __nv_bfloat162 b,
292 __nv_bfloat162 c) {
293 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
294 assert(false);
295 #else
296 return __hfma2(a, b, c);
297 #endif
298 __builtin_unreachable(); // Suppress missing return statement warning
299 }
300
301 inline __device__ __nv_bfloat162 fma(__nv_bfloat16 a, __nv_bfloat162 b,
302 __nv_bfloat162 c) {
303 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
304 assert(false);
305 #else
306 return __hfma2(bf162bf162(a), b, c);
307 #endif
308 __builtin_unreachable(); // Suppress missing return statement warning
309 }
310
311 inline __device__ bf16_4_t fma(bf16_4_t a, bf16_4_t b, bf16_4_t c) {
312 bf16_4_t d;
313 d.x = fma(a.x, b.x, c.x);
314 d.y = fma(a.y, b.y, c.y);
315 return d;
316 }
317
318 inline __device__ bf16_4_t fma(__nv_bfloat16 a, bf16_4_t b, bf16_4_t c) {
319 __nv_bfloat162 s = bf162bf162(a);
320 bf16_4_t d;
321 d.x = fma(s, b.x, c.x);
322 d.y = fma(s, b.y, c.y);
323 return d;
324 }
325
326 inline __device__ bf16_8_t fma(bf16_8_t a, bf16_8_t b, bf16_8_t c) {
327 bf16_8_t d;
328 d.x = fma(a.x, b.x, c.x);
329 d.y = fma(a.y, b.y, c.y);
330 d.z = fma(a.z, b.z, c.z);
331 d.w = fma(a.w, b.w, c.w);
332 return d;
333 }
334
335 inline __device__ bf16_8_t fma(__nv_bfloat16 a, bf16_8_t b, bf16_8_t c) {
336 __nv_bfloat162 s = bf162bf162(a);
337 bf16_8_t d;
338 d.x = fma(s, b.x, c.x);
339 d.y = fma(s, b.y, c.y);
340 d.z = fma(s, b.z, c.z);
341 d.w = fma(s, b.w, c.w);
342 return d;
343 }
344
345 inline __device__ float fma(__nv_bfloat16 a, __nv_bfloat16 b, float fc) {
346 return __bfloat162float(a) * __bfloat162float(b) + fc;
347 }
348
349 inline __device__ float2 fma(__nv_bfloat162 a, __nv_bfloat162 b, float2 fc) {
350 float2 fa = bf1622float2(a);
351 float2 fb = bf1622float2(b);
352 return fma(fa, fb, fc);
353 }
354
355 inline __device__ float2 fma(__nv_bfloat16 a, __nv_bfloat162 b, float2 fc) {
356 return fma(bf162bf162(a), b, fc);
357 }
358
359 inline __device__ Float4_ fma(bf16_4_t a, bf16_4_t b, Float4_ fc) {
360 Float4_ fd;
361 fd.x = fma(a.x, b.x, fc.x);
362 fd.y = fma(a.y, b.y, fc.y);
363 return fd;
364 }
365
366 inline __device__ Float4_ fma(__nv_bfloat16 a, bf16_4_t b, Float4_ fc) {
367 __nv_bfloat162 s = bf162bf162(a);
368 Float4_ fd;
369 fd.x = fma(s, b.x, fc.x);
370 fd.y = fma(s, b.y, fc.y);
371 return fd;
372 }
373
374 inline __device__ Float8_ fma(bf16_8_t a, bf16_8_t b, Float8_ fc) {
375 Float8_ fd;
376 fd.x = fma(a.x, b.x, fc.x);
377 fd.y = fma(a.y, b.y, fc.y);
378 fd.z = fma(a.z, b.z, fc.z);
379 fd.w = fma(a.w, b.w, fc.w);
380 return fd;
381 }
382
383 inline __device__ Float8_ fma(__nv_bfloat16 a, bf16_8_t b, Float8_ fc) {
384 __nv_bfloat162 s = bf162bf162(a);
385 Float8_ fd;
386 fd.x = fma(s, b.x, fc.x);
387 fd.y = fma(s, b.y, fc.y);
388 fd.z = fma(s, b.z, fc.z);
389 fd.w = fma(s, b.w, fc.w);
390 return fd;
391 }
392
393 // Vector sum.
394 template <>
395 inline __device__ float sum(__nv_bfloat16 v) {
396 return __bfloat162float(v);
397 }
398
399 template <>
400 inline __device__ float sum(__nv_bfloat162 v) {
401 float2 vf = bf1622float2(v);
402 return vf.x + vf.y;
403 }
404
405 template <>
406 inline __device__ float sum(bf16_4_t v) {
407 return sum(v.x) + sum(v.y);
408 }
409
410 template <>
411 inline __device__ float sum(bf16_8_t v) {
412 return sum(v.x) + sum(v.y) + sum(v.z) + sum(v.w);
413 }
414
415 // From float32 to bfloat16.
416 inline __device__ void from_float(__nv_bfloat16& dst, float src) {
417 dst = __float2bfloat16(src);
418 }
419
420 inline __device__ void from_float(__nv_bfloat162& dst, float2 src) {
421 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
422 assert(false);
423 #else
424 dst = __float22bfloat162_rn(src);
425 #endif
426 }
427
428 inline __device__ void from_float(bf16_4_t& dst, Float4_ src) {
429 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
430 assert(false);
431 #else
432 dst.x = __float22bfloat162_rn(src.x);
433 dst.y = __float22bfloat162_rn(src.y);
434 #endif
435 }
436
437 inline __device__ void from_float(bf16_8_t& dst, Float8_ src) {
438 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
439 assert(false);
440 #else
441 dst.x = __float22bfloat162_rn(src.x);
442 dst.y = __float22bfloat162_rn(src.y);
443 dst.z = __float22bfloat162_rn(src.z);
444 dst.w = __float22bfloat162_rn(src.w);
445 #endif
446 }
447
448 // From bfloat16 to float32.
449 inline __device__ float to_float(__nv_bfloat16 u) {
450 return __bfloat162float(u);
451 }
452
453 // Zero-out a variable.
454 inline __device__ void zero(__nv_bfloat16& dst) {
455 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
456 assert(false);
457 #else
458 // Same as CUDART_ZERO_BF16 introduced in CUDA 12.2.
459 dst = __ushort_as_bfloat16((unsigned short)0x0000U);
460 #endif
461 }
462
463 } // namespace vllm