char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Piotr Wilkin (ilintar)CUDA/HIP: Flash Attention tuning (gfx1201) (#28102)16378d93f

char/aliceai-t5-moe
47.4 KiB1298 linesraw
1#pragma once
2
3#include "common.cuh"
4#include "convert.cuh"
5#include "vecdotq.cuh"
6
7#include <cstdint>
8
9#define FATTN_KQ_STRIDE       256
10#define HALF_MAX_HALF         __float2half(65504.0f/2) // Use neg. of this instead of -INFINITY to initialize KQ max vals to avoid NaN upon subtraction.
11#define SOFTMAX_FTZ_THRESHOLD -20.0f                   // Softmax exp. of values smaller than this are flushed to zero to avoid NaNs.
12
13// log(2) = 0.6931, by adding this to the KQ maximum used for the softmax the numerical range representable
14//     by the VKQ accumulators is effectively being shifted up by a factor of 2.
15// This reduces issues with numerical overflow but also causes larger values to be flushed to zero.
16// However, as the output from FlashAttention will usually be used as an input for a matrix multiplication this should be negligible.
17// Still, the value range should be shifted as much as necessary but as little as possible.
18// The macro on the following line shifts it by a factor of 2**3=8, as was needed to fix https://github.com/ggml-org/llama.cpp/issues/18606 .
19#define FATTN_KQ_MAX_OFFSET (3.0f*0.6931f)
20
21typedef void (* fattn_kernel_t)(
22        const char * __restrict__ Q,
23        const char * __restrict__ K,
24        const char * __restrict__ V,
25        const char * __restrict__ mask,
26        const char * __restrict__ sinks,
27        const int  * __restrict__ KV_max,
28        float      * __restrict__ dst,
29        float2     * __restrict__ dst_meta,
30        const float scale,
31        const float max_bias,
32        const float m0,
33        const float m1,
34        const uint32_t n_head_log2,
35        const float logit_softcap,
36        const int32_t ne00, const uint3   ne01, const int32_t ne02, const int32_t ne03,
37                            const int32_t nb01, const int32_t nb02, const int32_t nb03,
38        const int32_t ne10, const int32_t ne11, const int32_t ne12, const int32_t ne13,
39                            const int32_t nb11, const int32_t nb12, const int64_t nb13,
40                            const int32_t nb21, const int32_t nb22, const int64_t nb23,
41                            const int32_t ne31, const int32_t ne32, const int32_t ne33,
42                            const int32_t nb31, const int32_t nb32, const int64_t nb33);
43
44typedef float (*vec_dot_KQ_t)(
45    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8 , const void * __restrict__ Q_ds);
46
47struct ggml_cuda_flash_attn_ext_f16_extra_data {
48    uintptr_t K;
49    uintptr_t V;
50    uintptr_t end;
51};
52
53static inline ggml_cuda_flash_attn_ext_f16_extra_data ggml_cuda_flash_attn_ext_get_f16_extra_data(
54        const ggml_tensor * dst, const bool need_f16_K, const bool need_f16_V) {
55    GGML_ASSERT(dst->op == GGML_OP_FLASH_ATTN_EXT);
56
57    const ggml_tensor * K = dst->src[1];
58    const ggml_tensor * V = dst->src[2];
59
60    GGML_ASSERT(K != nullptr);
61    GGML_ASSERT(V != nullptr);
62
63    const bool V_is_K_view = V->view_src && (V->view_src == K || (V->view_src == K->view_src && V->view_offs == K->view_offs));
64
65    ggml_cuda_flash_attn_ext_f16_extra_data data = {};
66    data.end = (uintptr_t) dst->data + ggml_nbytes(dst);
67
68    if (need_f16_K && K->type != GGML_TYPE_F16) {
69        data.end = GGML_PAD(data.end, 128);
70        data.K   = data.end;
71        data.end += ggml_nelements(K)*ggml_type_size(GGML_TYPE_F16);
72    }
73
74    if (need_f16_V && V->type != GGML_TYPE_F16) {
75        if (V_is_K_view) {
76            data.V = data.K;
77        } else {
78            data.end = GGML_PAD(data.end, 128);
79            data.V   = data.end;
80            data.end += ggml_nelements(V)*ggml_type_size(GGML_TYPE_F16);
81        }
82    }
83
84    return data;
85}
86
87template <int D, int nthreads>
88static __device__ __forceinline__ float vec_dot_fattn_vec_KQ_f16(
89    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8 , const void * __restrict__ Q_ds_v) {
90
91    const half2 * K_h2 = (const half2 *) K_c;
92    GGML_UNUSED(Q_q8);
93    GGML_UNUSED(Q_ds_v);
94
95    constexpr int cpy_nb = ggml_cuda_get_max_cpy_bytes();
96    constexpr int cpy_ne = cpy_nb / 4;
97
98    float sum = 0.0f;
99
100#pragma unroll
101    for (int k_KQ_0 = 0; k_KQ_0 < D/2; k_KQ_0 += nthreads*cpy_ne) {
102        __align__(16) half2 tmp[cpy_ne];
103        ggml_cuda_memcpy_1<sizeof(tmp)>(tmp, K_h2 + k_KQ_0 + (threadIdx.x % nthreads)*cpy_ne);
104#pragma unroll
105        for (int k_KQ_1 = 0; k_KQ_1 < cpy_ne; ++k_KQ_1) {
106#ifdef V_DOT2_F32_F16_AVAILABLE
107            ggml_cuda_mad(sum,                tmp[k_KQ_1] , ((const half2  *) Q_v)[k_KQ_0/nthreads + k_KQ_1]);
108#else
109            ggml_cuda_mad(sum, __half22float2(tmp[k_KQ_1]), ((const float2 *) Q_v)[k_KQ_0/nthreads + k_KQ_1]);
110#endif // V_DOT2_F32_F16_AVAILABLE
111        }
112    }
113
114    return sum;
115}
116
117template <int D, int nthreads>
118static __device__ __forceinline__ float vec_dot_fattn_vec_KQ_bf16(
119    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8 , const void * __restrict__ Q_ds_v) {
120
121    const nv_bfloat162 * K_bf16 = (const nv_bfloat162 *) K_c;
122    GGML_UNUSED(Q_q8);
123    GGML_UNUSED(Q_ds_v);
124
125    constexpr int cpy_nb = ggml_cuda_get_max_cpy_bytes();
126    constexpr int cpy_ne = cpy_nb / 4;
127
128    float sum = 0.0f;
129
130#pragma unroll
131    for (int k_KQ_0 = 0; k_KQ_0 < D/2; k_KQ_0 += nthreads*cpy_ne) {
132        __align__(16) nv_bfloat162 tmp[cpy_ne];
133        ggml_cuda_memcpy_1<sizeof(tmp)>(tmp, K_bf16 + k_KQ_0 + (threadIdx.x % nthreads)*cpy_ne);
134#pragma unroll
135        for (int k_KQ_1 = 0; k_KQ_1 < cpy_ne; ++k_KQ_1) {
136#ifdef V_DOT2_F32_F16_AVAILABLE
137            // FIXME replace macros in vector FA kernel with templating and use FP32 for BF16
138            ggml_cuda_mad(sum, ggml_cuda_cast<float2>(tmp[k_KQ_1]), __half22float2(((const half2 *) Q_v)[k_KQ_0/nthreads + k_KQ_1]));
139#else
140            ggml_cuda_mad(sum, ggml_cuda_cast<float2>(tmp[k_KQ_1]), ((const float2 *) Q_v)[k_KQ_0/nthreads + k_KQ_1]);
141#endif // V_DOT2_F32_F16_AVAILABLE
142        }
143    }
144
145    return sum;
146}
147
148template<int D, int nthreads>
149static __device__ __forceinline__ float vec_dot_fattn_vec_KQ_q4_0(
150    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) {
151
152    const block_q4_0 * K_q4_0 = (const block_q4_0 *) K_c;
153    GGML_UNUSED(Q_v);
154
155    float sum = 0.0f;
156
157#pragma unroll
158    for (int k_KQ_0 = 0; k_KQ_0 < int(D/sizeof(int)); k_KQ_0 += nthreads) {
159        const int k_KQ = k_KQ_0 + (nthreads == WARP_SIZE ? threadIdx.x : threadIdx.x % nthreads);
160
161        const int ib    = k_KQ /  QI8_1;
162        const int iqs4  = k_KQ %  QI4_0;
163        const int shift = k_KQ & (QI8_1/2);
164
165        int v;
166        ggml_cuda_memcpy_1<sizeof(int), 2>(&v, K_q4_0[ib].qs + sizeof(int)*iqs4);
167        v = (v >> shift) & 0x0F0F0F0F;
168        const int u = Q_q8[k_KQ_0/nthreads];
169
170        const int sumi = ggml_cuda_dp4a(v, u, 0);
171
172        const float2 Q_ds = ((const float2 *) Q_ds_v)[k_KQ_0/nthreads];
173        sum += __half2float(K_q4_0[ib].d) * (sumi*Q_ds.x - (8/QI8_1)*Q_ds.y);
174    }
175
176    return sum;
177}
178
179template<int D, int nthreads>
180static __device__ __forceinline__ float vec_dot_fattn_vec_KQ_q4_1(
181    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) {
182
183    const block_q4_1 * K_q4_1 = (const block_q4_1 *) K_c;
184    GGML_UNUSED(Q_v);
185
186    float sum = 0.0f;
187
188#pragma unroll
189    for (int k_KQ_0 = 0; k_KQ_0 < int(D/sizeof(int)); k_KQ_0 += nthreads) {
190        const int k_KQ = k_KQ_0 + (nthreads == WARP_SIZE ? threadIdx.x : threadIdx.x % nthreads);
191
192        const int ib    = k_KQ /  QI8_1;
193        const int iqs4  = k_KQ %  QI4_1;
194        const int shift = k_KQ & (QI8_1/2);
195
196        int v;
197        ggml_cuda_memcpy_1<sizeof(int)>(&v, K_q4_1[ib].qs + sizeof(int)*iqs4);
198        v = (v >> shift) & 0x0F0F0F0F;
199        const int u = Q_q8[k_KQ_0/nthreads];
200
201        const int sumi = ggml_cuda_dp4a(v, u, 0);
202
203        const float2 K_dm = __half22float2(K_q4_1[ib].dm);
204        const float2 Q_ds = ((const float2 *) Q_ds_v)[k_KQ_0/nthreads];
205
206        sum += K_dm.x*Q_ds.x*sumi + K_dm.y*Q_ds.y/QI8_1;
207    }
208
209    return sum;
210}
211
212template<int D, int nthreads>
213static __device__ __forceinline__ float vec_dot_fattn_vec_KQ_q5_0(
214    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) {
215
216    const block_q5_0 * K_q5_0 = (const block_q5_0 *) K_c;
217    GGML_UNUSED(Q_v);
218
219    float sum = 0.0f;
220
221#pragma unroll
222    for (int k_KQ_0 = 0; k_KQ_0 < int(D/sizeof(int)); k_KQ_0 += nthreads) {
223        const int k_KQ = k_KQ_0 + (nthreads == WARP_SIZE ? threadIdx.x : threadIdx.x % nthreads);
224
225        const int ib    = k_KQ /  QI8_1;
226        const int iqs4  = k_KQ %  QI5_0;
227        const int iqs8  = k_KQ %  QI8_1;
228        const int shift = k_KQ & (QI8_1/2);
229
230        int v;
231        ggml_cuda_memcpy_1<sizeof(int), 2>(&v, K_q5_0[ib].qs + sizeof(int)*iqs4);
232        v = (v >> shift) & 0x0F0F0F0F;
233
234        {
235            int vh;
236            ggml_cuda_memcpy_1<sizeof(int), 2>(&vh, K_q5_0[ib].qh);
237            vh >>= iqs8 * QI5_0;
238
239            v |= (vh <<  4) & 0x00000010; // 0 ->  4
240            v |= (vh << 11) & 0x00001000; // 1 -> 12
241            v |= (vh << 18) & 0x00100000; // 2 -> 20
242            v |= (vh << 25) & 0x10000000; // 3 -> 28
243        }
244
245        const int u = Q_q8[k_KQ_0/nthreads];
246
247        const int sumi = ggml_cuda_dp4a(v, u, 0);
248
249        const float2 Q_ds = ((const float2 *) Q_ds_v)[k_KQ_0/nthreads];
250
251        sum += __half2float(K_q5_0[ib].d) * (sumi*Q_ds.x - (16/QI8_1)*Q_ds.y);
252    }
253
254    return sum;
255}
256
257template<int D, int nthreads>
258static __device__ __forceinline__ float vec_dot_fattn_vec_KQ_q5_1(
259    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) {
260
261    const block_q5_1 * K_q5_1 = (const block_q5_1 *) K_c;
262    GGML_UNUSED(Q_v);
263
264    float sum = 0.0f;
265
266#pragma unroll
267    for (int k_KQ_0 = 0; k_KQ_0 < int(D/sizeof(int)); k_KQ_0 += nthreads) {
268        const int k_KQ = k_KQ_0 + (nthreads == WARP_SIZE ? threadIdx.x : threadIdx.x % nthreads);
269
270        const int ib    = k_KQ /  QI8_1;
271        const int iqs4  = k_KQ %  QI5_1;
272        const int iqs8  = k_KQ %  QI8_1;
273        const int shift = k_KQ & (QI8_1/2);
274
275        int v;
276        ggml_cuda_memcpy_1<sizeof(int)>(&v, K_q5_1[ib].qs + sizeof(int)*iqs4);
277        v = (v >> shift) & 0x0F0F0F0F;
278
279        {
280            int vh;
281            ggml_cuda_memcpy_1<sizeof(int)>(&vh, K_q5_1[ib].qh);
282            vh >>= iqs8 * QI5_0;
283
284            v |= (vh <<  4) & 0x00000010; // 0 ->  4
285            v |= (vh << 11) & 0x00001000; // 1 -> 12
286            v |= (vh << 18) & 0x00100000; // 2 -> 20
287            v |= (vh << 25) & 0x10000000; // 3 -> 28
288        }
289
290        const int u = Q_q8[k_KQ_0/nthreads];
291
292        const int sumi = ggml_cuda_dp4a(v, u, 0);
293
294        const float2 K_dm = __half22float2(K_q5_1[ib].dm);
295        const float2 Q_ds = ((const float2 *) Q_ds_v)[k_KQ_0/nthreads];
296
297        sum += K_dm.x*Q_ds.x*sumi + K_dm.y*Q_ds.y/QI8_1;
298    }
299
300    return sum;
301}
302
303template <int D, int nthreads>
304static __device__ __forceinline__ float vec_dot_fattn_vec_KQ_q8_0(
305    const char * __restrict__ K_c, const void * __restrict__ Q_v, const int * __restrict__ Q_q8, const void * __restrict__ Q_ds_v) {
306
307    const block_q8_0 * K_q8_0 = (const block_q8_0 *) K_c;
308    GGML_UNUSED(Q_v);
309
310    float sum = 0.0f;
311
312#pragma unroll
313    for (int k_KQ_0 = 0; k_KQ_0 < int(D/sizeof(int)); k_KQ_0 += nthreads) {
314        const int k_KQ = k_KQ_0 + (nthreads == WARP_SIZE ? threadIdx.x : threadIdx.x % nthreads);
315
316        const int ib  = k_KQ / QI8_0;
317        const int iqs = k_KQ % QI8_0;
318
319        int v;
320        ggml_cuda_memcpy_1<sizeof(v), 2>(&v, K_q8_0[ib].qs + 4*iqs);
321
322        const float2 * Q_ds = (const float2 *) Q_ds_v;
323        const float Q_d = Q_ds[k_KQ_0/nthreads].x;
324
325        sum += vec_dot_q8_0_q8_1_impl<float, 1>(&v, &Q_q8[k_KQ_0/nthreads], K_q8_0[ib].d, Q_d);
326    }
327
328    return sum;
329}
330
331template <typename Tds, int ni>
332static __device__ __forceinline__ void quantize_q8_1_to_shared(
333    const float * __restrict__ x, const float scale, int * __restrict__ yq32, void * __restrict__ yds) {
334
335    float vals[sizeof(int)] = {0.0f};
336#pragma unroll
337    for (int l = 0; l < int(sizeof(int)); ++l) {
338        vals[l] = (ni == WARP_SIZE || threadIdx.x < ni) ? scale * x[4*threadIdx.x + l] : 0.0f;
339    }
340
341    float amax = fabsf(vals[0]);
342    float sum  = vals[0];
343#pragma unroll
344    for (int l = 1; l < int(sizeof(int)); ++l) {
345        amax = fmaxf(amax, fabsf(vals[l]));
346        sum += vals[l];
347    }
348#pragma unroll
349    for (int mask = QI8_1/2; mask > 0; mask >>= 1) {
350        amax = fmaxf(amax, __shfl_xor_sync(0xFFFFFFFF, amax, mask, 32));
351        sum +=             __shfl_xor_sync(0xFFFFFFFF, sum,  mask, 32);
352    }
353
354    const float d = amax / 127;
355    int q32 = 0;
356    int8_t * q8 = (int8_t *) &q32;
357
358    if (d != 0.0f) {
359#pragma unroll
360        for (int l = 0; l < int(sizeof(int)); ++l) {
361            q8[l] = roundf(vals[l] / d);
362        }
363    }
364
365    yq32[threadIdx.x] = q32;
366    if (threadIdx.x % QI8_1 == 0 && (ni == WARP_SIZE || threadIdx.x < ni)) {
367        if (std::is_same<Tds, half2>::value) {
368            ((half2  *) yds)[threadIdx.x/QI8_1] =  make_half2(d, sum);
369        } else {
370            ((float2 *) yds)[threadIdx.x/QI8_1] = make_float2(d, sum);
371        }
372    }
373}
374
375typedef void (*dequantize_V_t)(const void *, void *, const int64_t);
376
377template <typename T, int ne>
378static __device__ __forceinline__ void dequantize_V_f16(const void * __restrict__ vx, void * __restrict__ dst, const int64_t i0) {
379    if constexpr (std::is_same_v<T, half>) {
380        ggml_cuda_memcpy_1<ne*sizeof(half)>(dst, (const half *) vx + i0);
381    } else if constexpr (std::is_same_v<T, float>) {
382        static_assert(ne % 2 == 0, "bad ne");
383        __align__(16) half2 tmp[ne/2];
384        ggml_cuda_memcpy_1<ne*sizeof(half)>(tmp, (const half *) vx + i0);
385        float2 * dst_f2 = (float2 *) dst;
386#pragma unroll
387        for (int l = 0; l < ne/2; ++l) {
388            dst_f2[l] = __half22float2(tmp[l]);
389        }
390    } else {
391        static_assert(std::is_same_v<T, void>, "unsupported type");
392    }
393}
394
395template <typename T, int ne>
396static __device__ __forceinline__ void dequantize_V_bf16(const void * __restrict__ vx, void * __restrict__ dst, const int64_t i0) {
397    static_assert(std::is_same_v<T, float>, "BF16 V dequantization only supports float output");
398    static_assert(ne % 2 == 0, "bad ne");
399    __align__(16) nv_bfloat162 tmp[ne/2];
400    ggml_cuda_memcpy_1<ne*sizeof(nv_bfloat16)>(tmp, (const nv_bfloat16 *) vx + i0);
401    float2 * dst_f2 = (float2 *) dst;
402#pragma unroll
403    for (int l = 0; l < ne/2; ++l) {
404        dst_f2[l] = ggml_cuda_cast<float2>(tmp[l]);
405    }
406}
407
408template <typename T, int ne>
409static __device__ __forceinline__ void dequantize_V_q4_0(const void * __restrict__ vx, void * __restrict__ dst, const int64_t i0) {
410    const block_q4_0 * x = (const block_q4_0 *) vx;
411
412    const int64_t ib    =  i0          /  QK4_0;
413    const int     iqs   =  i0          % (QK4_0/2);
414    const int     shift = (i0 % QK4_0) / (QK4_0/2);
415
416    int q;
417    static_assert(ne == 2 || ne == 4, "bad ne");
418    ggml_cuda_memcpy_1<ne, 2>(&q, x[ib].qs + iqs);
419    q >>= 4*shift;
420    q &= 0x0F0F0F0F;
421    q = __vsubss4(q, 0x08080808);
422
423    const int8_t * q8 = (const int8_t *) &q;
424
425#ifdef FP16_AVAILABLE
426    if constexpr (std::is_same_v<T, half>) {
427        const half2 d = __half2half2(x[ib].d);
428
429#pragma unroll
430        for (int l0 = 0; l0 < ne; l0 += 2) {
431            ((half2 *) dst)[l0/2] = d * make_half2(q8[l0 + 0], q8[l0 + 1]);
432        }
433    } else
434#endif // FP16_AVAILABLE
435    if constexpr (std::is_same_v<T, float>) {
436        const float d = x[ib].d;
437
438#pragma unroll
439        for (int l = 0; l < ne; ++l) {
440            ((float *) dst)[l] = d * q8[l];
441        }
442    } else {
443        static_assert(std::is_same_v<T, void>, "bad type");
444    }
445}
446
447template <typename T, int ne>
448static __device__ __forceinline__ void dequantize_V_q4_1(const void * __restrict__ vx, void * __restrict__ dst, const int64_t i0) {
449    const block_q4_1 * x = (const block_q4_1 *) vx;
450
451    const int64_t ib    =  i0          /  QK4_1;
452    const int     iqs   =  i0          % (QK4_1/2);
453    const int     shift = (i0 % QK4_1) / (QK4_1/2);
454
455    int q;
456    static_assert(ne == 2 || ne == 4, "bad ne");
457    ggml_cuda_memcpy_1<ne>(&q, x[ib].qs + iqs);
458    q >>= 4*shift;
459    q &= 0x0F0F0F0F;
460
461    const int8_t * q8 = (const int8_t *) &q;
462
463#ifdef FP16_AVAILABLE
464    if constexpr (std::is_same_v<T, half>) {
465        const half2 dm = x[ib].dm;
466        const half2 d  = __half2half2( __low2half(dm));
467        const half2 m  = __half2half2(__high2half(dm));
468
469#pragma unroll
470        for (int l0 = 0; l0 < ne; l0 += 2) {
471            ((half2 *) dst)[l0/2] = d * make_half2(q8[l0 + 0], q8[l0 + 1]) + m;
472        }
473    } else
474#endif // FP16_AVAILABLE
475    if constexpr (std::is_same_v<T, float>) {
476        const float2 dm = __half22float2(x[ib].dm);
477
478#pragma unroll
479        for (int l = 0; l < ne; ++l) {
480            ((float *) dst)[l] = dm.x * q8[l] + dm.y;
481        }
482    } else {
483        static_assert(std::is_same_v<T, void>, "bad type");
484    }
485}
486
487template <typename T, int ne>
488static __device__ __forceinline__ void dequantize_V_q5_0(const void * __restrict__ vx, void * __restrict__ dst, const int64_t i0) {
489    const block_q5_0 * x = (const block_q5_0 *) vx;
490
491    const int64_t ib    =  i0          /  QK5_0;
492    const int     idq   =  i0          %  QK5_0;
493    const int     iqs   =  i0          % (QK5_0/2);
494    const int     shift = (i0 % QK5_0) / (QK5_0/2);
495
496    int q;
497    static_assert(ne == 2 || ne == 4, "bad ne");
498    ggml_cuda_memcpy_1<ne, 2>(&q, x[ib].qs + iqs);
499    q >>= 4*shift;
500    q &= 0x0F0F0F0F;
501
502    {
503        int qh;
504        ggml_cuda_memcpy_1<ne, 2>(&qh, x[ib].qh);
505#pragma unroll
506        for (int l = 0; l < ne; ++l) {
507            q |= ((qh >> (idq + l)) & 0x00000001) << (8*l + 4);
508        }
509    }
510
511    q = __vsubss4(q, 0x10101010);
512
513    const int8_t * q8 = (const int8_t *) &q;
514
515#ifdef FP16_AVAILABLE
516    if constexpr (std::is_same_v<T, half>) {
517        const half2 d = __half2half2(x[ib].d);
518
519#pragma unroll
520        for (int l0 = 0; l0 < ne; l0 += 2) {
521            ((half2 *) dst)[l0/2] = d * make_half2(q8[l0 + 0], q8[l0 + 1]);
522        }
523    } else
524#endif // FP16_AVAILABLE
525    if constexpr (std::is_same_v<T, float>) {
526        const float d = x[ib].d;
527
528#pragma unroll
529        for (int l = 0; l < ne; ++l) {
530            ((float *) dst)[l] = d * q8[l];
531        }
532    } else {
533        static_assert(std::is_same_v<T, void>, "bad type");
534    }
535}
536
537template <typename T, int ne>
538static __device__ __forceinline__ void dequantize_V_q5_1(const void * __restrict__ vx, void * __restrict__ dst, const int64_t i0) {
539    const block_q5_1 * x = (const block_q5_1 *) vx;
540
541    const int64_t ib    =  i0          /  QK5_1;
542    const int     idq   =  i0          %  QK5_1;
543    const int     iqs   =  i0          % (QK5_1/2);
544    const int     shift = (i0 % QK5_1) / (QK5_1/2);
545
546    int q;
547    static_assert(ne == 2 || ne == 4, "bad ne");
548    ggml_cuda_memcpy_1<ne>(&q, x[ib].qs + iqs);
549    q >>= 4*shift;
550    q &= 0x0F0F0F0F;
551
552    {
553        int qh;
554        ggml_cuda_memcpy_1<ne>(&qh, x[ib].qh);
555#pragma unroll
556        for (int l = 0; l < ne; ++l) {
557            q |= ((qh >> (idq + l)) & 0x00000001) << (8*l + 4);
558        }
559    }
560
561    const int8_t * q8 = (const int8_t *) &q;
562
563#ifdef FP16_AVAILABLE
564    if constexpr (std::is_same_v<T, half>) {
565        const half2 dm = x[ib].dm;
566        const half2 d  = __half2half2( __low2half(dm));
567        const half2 m  = __half2half2(__high2half(dm));
568
569#pragma unroll
570        for (int l0 = 0; l0 < ne; l0 += 2) {
571            ((half2 *) dst)[l0/2] = d * make_half2(q8[l0 + 0], q8[l0 + 1]) + m;
572        }
573    } else
574#endif // FP16_AVAILABLE
575    if constexpr (std::is_same_v<T, float>) {
576        const float2 dm = __half22float2(x[ib].dm);
577
578#pragma unroll
579        for (int l = 0; l < ne; ++l) {
580            ((float *) dst)[l] = dm.x * q8[l] + dm.y;
581        }
582    } else {
583        static_assert(std::is_same_v<T, void>, "bad type");
584    }
585}
586
587template <typename T, int ne>
588static __device__ __forceinline__ void dequantize_V_q8_0(const void * __restrict__ vx, void * __restrict__ dst, const int64_t i0) {
589    const block_q8_0 * x = (const block_q8_0 *) vx;
590
591    const int64_t ib  = i0 / QK8_0;
592    const int     iqs = i0 % QK8_0;
593
594    static_assert(ne % 2 == 0, "bad ne");
595    int8_t qs[ne];
596    ggml_cuda_memcpy_1<ne, 2>(qs, x[ib].qs + iqs);
597
598#ifdef FP16_AVAILABLE
599    if constexpr (std::is_same<T, half>::value) {
600        const half2 d = __half2half2(x[ib].d);
601
602#pragma unroll
603        for (int l0 = 0; l0 < ne; l0 += 2) {
604            ((half2 *) dst)[l0/2] = d * make_half2(qs[l0 + 0], qs[l0 + 1]);
605        }
606    } else
607#endif // FP16_AVAILABLE
608    if constexpr (std::is_same<T, float>::value) {
609        const float d = x[ib].d;
610
611#pragma unroll
612        for (int l = 0; l < ne; ++l) {
613            ((float *) dst)[l] = d * qs[l];
614        }
615    } else {
616        static_assert(std::is_same_v<T, void>, "unsupported type");
617    }
618}
619
620template <ggml_type type_K, int D, int nthreads>
621constexpr __device__ vec_dot_KQ_t get_vec_dot_KQ() {
622    if constexpr (type_K == GGML_TYPE_F16) {
623        return vec_dot_fattn_vec_KQ_f16<D, nthreads>;
624    } else if constexpr (type_K == GGML_TYPE_Q4_0) {
625        return vec_dot_fattn_vec_KQ_q4_0<D, nthreads>;
626    } else if constexpr (type_K == GGML_TYPE_Q4_1) {
627        return vec_dot_fattn_vec_KQ_q4_1<D, nthreads>;
628    } else if constexpr (type_K == GGML_TYPE_Q5_0) {
629        return vec_dot_fattn_vec_KQ_q5_0<D, nthreads>;
630    } else if constexpr (type_K == GGML_TYPE_Q5_1) {
631        return vec_dot_fattn_vec_KQ_q5_1<D, nthreads>;
632    } else if constexpr (type_K == GGML_TYPE_Q8_0) {
633        return vec_dot_fattn_vec_KQ_q8_0<D, nthreads>;
634    } else if constexpr (type_K == GGML_TYPE_BF16) {
635        return vec_dot_fattn_vec_KQ_bf16<D, nthreads>;
636    } else {
637        static_assert(type_K == -1, "bad type");
638        return nullptr;
639    }
640}
641
642template <ggml_type type_V, typename T, int ne>
643constexpr __device__ dequantize_V_t get_dequantize_V() {
644    if constexpr (type_V == GGML_TYPE_F16) {
645        return dequantize_V_f16<T, ne>;
646    } else if constexpr (type_V == GGML_TYPE_Q4_0) {
647        return dequantize_V_q4_0<T, ne>;
648    } else if constexpr (type_V == GGML_TYPE_Q4_1) {
649        return dequantize_V_q4_1<T, ne>;
650    } else if constexpr (type_V == GGML_TYPE_Q5_0) {
651        return dequantize_V_q5_0<T, ne>;
652    } else if constexpr (type_V == GGML_TYPE_Q5_1) {
653        return dequantize_V_q5_1<T, ne>;
654    } else if constexpr (type_V == GGML_TYPE_Q8_0) {
655        return dequantize_V_q8_0<T, ne>;
656    } else if constexpr (type_V == GGML_TYPE_BF16) {
657        return dequantize_V_bf16<float, ne>;
658    } else {
659        static_assert(type_V == -1, "bad type");
660        return nullptr;
661    }
662}
663
664template <int ncols1>
665__launch_bounds__(FATTN_KQ_STRIDE/2, 1)
666static __global__ void flash_attn_mask_to_KV_max(
667        const half2 * mask_ptr, int * KV_max_ptr, const int ne30, const int64_t s31, const int64_t s33) {
668    const half2 * GGML_CUDA_RESTRICT mask   = mask_ptr;
669    int         * GGML_CUDA_RESTRICT KV_max = KV_max_ptr;
670
671    const int ne31     = gridDim.x;
672    const int tid      = threadIdx.x;
673    const int sequence = blockIdx.y;
674    const int jt       = blockIdx.x;
675
676    mask += sequence*s33 + jt*ncols1*s31;
677
678    __shared__ int buf_iw[WARP_SIZE];
679    if (tid < WARP_SIZE) {
680        buf_iw[tid] = 1;
681    }
682    ggml_cuda_pdl_sync();
683    __syncthreads();
684
685    int KV_max_sj = (ne30 - 1) * FATTN_KQ_STRIDE;
686    for (; KV_max_sj >= 0; KV_max_sj -= FATTN_KQ_STRIDE) {
687        int all_inf = 1;
688
689#pragma unroll
690        for (int j = 0; j < ncols1; ++j) {
691            const float2 tmp = __half22float2(mask[j*s31 + KV_max_sj/2 + tid]);
692            all_inf = all_inf && int(isinf(tmp.x)) && int(isinf(tmp.y));
693        }
694
695        all_inf = warp_reduce_all(all_inf);
696        if (tid % WARP_SIZE == 0) {
697            buf_iw[tid / WARP_SIZE] = all_inf;
698        }
699        __syncthreads();
700        all_inf = buf_iw[tid % WARP_SIZE];
701        __syncthreads();
702        all_inf = warp_reduce_all(all_inf);
703
704        if (!all_inf) {
705            break;
706        }
707    }
708
709    // If the break in the loop was not triggered, KV_max_sj is now -FATTN_KQ_STRIDE.
710    // If the break was triggered it's the lower edge of the tile with the first non-masked values.
711    // In either case, walk back the decrementation by FATTN_KQ_STRIDE.
712    KV_max_sj += FATTN_KQ_STRIDE;
713
714    if (threadIdx.x != 0) {
715        return;
716    }
717
718    KV_max[sequence*ne31 + jt] = KV_max_sj;
719}
720
721void ggml_cuda_flash_attn_ext_compact_mask(
722        const ggml_tensor * mask, int32_t * indices, int32_t n_kv_max, cudaStream_t stream);
723
724template<int D, int ncols1, int ncols2> // D == head size
725__launch_bounds__(D, 1)
726static __global__ void flash_attn_stream_k_fixup_uniform(
727        float * dst_ptr,
728        const float2 * dst_fixup_ptr,
729        const int ne01, const int ne02,
730        const int ne12, const int nblocks_stream_k,
731        const int gqa_ratio,
732        const int blocks_per_tile,
733        const uint3 fd_iter_j_z_ne12,
734        const uint3 fd_iter_j_z,
735        const uint3 fd_iter_j) {
736    constexpr int ncols = ncols1*ncols2;
737    ggml_cuda_pdl_lc();
738    float        * GGML_CUDA_RESTRICT dst       = dst_ptr;
739    const float2 * GGML_CUDA_RESTRICT dst_fixup = dst_fixup_ptr;
740
741    const int tile_idx = blockIdx.x; // One block per output tile.
742    const int j        = blockIdx.y;
743    const int c        = blockIdx.z;
744    const int jc       = j*ncols2 + c;
745    const int tid      = threadIdx.x;
746
747    // nblocks_stream_k is a multiple of ntiles_dst (== gridDim.x), so each tile gets the same number of blocks.
748    const int b_first = tile_idx * blocks_per_tile;
749    const int b_last  = b_first + blocks_per_tile - 1;
750
751    const float * dst_fixup_data = ((const float *) dst_fixup) + nblocks_stream_k*(2*2*ncols);
752
753    // z_KV == K/V head index, zt_gqa = Q head start index per K/V head, jt = token position start index
754    const uint2 dm0 = fast_div_modulo(tile_idx, fd_iter_j_z_ne12);
755    const uint2 dm1 = fast_div_modulo(dm0.y,    fd_iter_j_z);
756    const uint2 dm2 = fast_div_modulo(dm1.y,    fd_iter_j);
757
758    const int sequence = dm0.x;
759    const int z_KV     = dm1.x;
760    const int zt_gqa   = dm2.x;
761    const int jt       = dm2.y;
762
763    const int zt_Q = z_KV*gqa_ratio + zt_gqa*ncols2; // Global Q head start index.
764
765    if (jt*ncols1 + j >= ne01 || zt_gqa*ncols2 + c >= gqa_ratio) {
766        return;
767    }
768
769    dst += sequence*ne02*ne01*D + jt*ne02*(ncols1*D) + zt_Q*D + (j*ne02 + c)*D + tid;
770
771    ggml_cuda_pdl_sync();
772    // Load the partial result that needs a fixup
773    float dst_val = *dst;
774    float max_val;
775    float rowsum;
776    {
777        const float2 tmp = dst_fixup[b_last*ncols + jc];
778        max_val = tmp.x;
779        rowsum  = tmp.y;
780    }
781
782    // Combine with all previous blocks in this tile.
783    for (int bidx = b_last - 1; bidx >= b_first; --bidx) {
784        const float dst_add = dst_fixup_data[bidx*ncols*D + jc*D + tid];
785
786        const float2 tmp = dst_fixup[(nblocks_stream_k + bidx)*ncols + jc];
787
788        const float max_val_new = fmaxf(max_val, tmp.x);
789
790        const float diff_val = max_val - max_val_new;
791        const float diff_add = tmp.x   - max_val_new;
792
793        const float scale_val = diff_val >= SOFTMAX_FTZ_THRESHOLD ? expf(diff_val) : 0.0f;
794        const float scale_add = diff_add >= SOFTMAX_FTZ_THRESHOLD ? expf(diff_add) : 0.0f;
795
796        dst_val = scale_val*dst_val + scale_add*dst_add;
797        rowsum  = scale_val*rowsum  + scale_add*tmp.y;
798
799        max_val = max_val_new;
800    }
801
802    // Write back final result:
803    *dst = dst_val / rowsum;
804}
805
806// General fixup kernel for the case where the number of blocks per tile is not uniform across tiles
807// (blocks_num.x not a multiple of ntiles_dst)
808template <int D, int ncols1, int ncols2> // D == head size
809__launch_bounds__(D, 1)
810static __global__ void flash_attn_stream_k_fixup_general(
811        float * dst_ptr,
812        const float2 * dst_fixup_ptr,
813        const int ne01, const int ne02,
814        const int gqa_ratio,
815        const int total_work,
816        const uint3 fd_iter_k_j_z_ne12,
817        const uint3 fd_iter_k_j_z,
818        const uint3 fd_iter_k_j,
819        const uint3 fd_iter_k) {
820    float        * GGML_CUDA_RESTRICT dst       = dst_ptr;
821    const float2 * GGML_CUDA_RESTRICT dst_fixup = dst_fixup_ptr;
822    constexpr int ncols = ncols1*ncols2;
823
824    const int bidx0 = blockIdx.x;
825    const int j     = blockIdx.y;
826    const int c     = blockIdx.z;
827    const int jc    = j*ncols2 + c;
828    const int tid   = threadIdx.x;
829
830    const float * dst_fixup_data = ((const float *) dst_fixup) + gridDim.x*(2*2*ncols);
831
832    const int kbc0      = int64_t(bidx0 + 0)*total_work / gridDim.x;
833    const int kbc0_stop = int64_t(bidx0 + 1)*total_work / gridDim.x;
834
835    const bool did_not_have_any_data   = kbc0 == kbc0_stop;
836    const bool wrote_beginning_of_tile = fastmodulo(kbc0, fd_iter_k) == 0;
837    const bool did_not_write_last      = fastdiv(kbc0, fd_iter_k) == fastdiv(kbc0_stop, fd_iter_k) && fastmodulo(kbc0_stop, fd_iter_k) != 0;
838    if (did_not_have_any_data || wrote_beginning_of_tile || did_not_write_last) {
839        return;
840    }
841
842    // z_KV == K/V head index, zt_gqa = Q head start index per K/V head, jt = token position start index
843    const uint2 dm0 = fast_div_modulo(kbc0, fd_iter_k_j_z_ne12);
844    const uint2 dm1 = fast_div_modulo(dm0.y, fd_iter_k_j_z);
845    const uint2 dm2 = fast_div_modulo(dm1.y, fd_iter_k_j);
846    const uint2 dm3 = fast_div_modulo(dm2.y, fd_iter_k);
847
848    const int sequence = dm0.x;
849    const int z_KV     = dm1.x;
850    const int zt_gqa   = dm2.x;
851    const int jt       = dm3.x;
852
853    const int zt_Q = z_KV*gqa_ratio + zt_gqa*ncols2; // Global Q head start index.
854
855    if (jt*ncols1 + j >= ne01 || zt_gqa*ncols2 + c >= gqa_ratio) {
856        return;
857    }
858
859    dst += sequence*ne02*ne01*D + jt*ne02*(ncols1*D) + zt_Q*D + (j*ne02 + c)*D + tid;
860
861    // Load the partial result that needs a fixup:
862    float dst_val = 0.0f;
863    float max_val = 0.0f;
864    float rowsum  = 0.0f;
865    ggml_cuda_pdl_sync();
866    {
867        dst_val = *dst;
868
869        const float2 tmp = dst_fixup[bidx0*ncols + jc];
870        max_val = tmp.x;
871        rowsum  = tmp.y;
872    }
873
874    // Iterate over previous blocks and compute the combined results.
875    // All CUDA blocks that get here must have a previous block that needs a fixup.
876    const int tile_kbc0 = fastdiv(kbc0, fd_iter_k);
877    int bidx = bidx0 - 1;
878    int kbc_stop = kbc0;
879    while(true) {
880        const int kbc = int64_t(bidx)*total_work / gridDim.x;
881        if (kbc == kbc_stop) { // Did not have any data.
882            bidx--;
883            kbc_stop = kbc;
884            continue;
885        }
886
887        const float dst_add = dst_fixup_data[bidx*ncols*D + jc*D + tid];
888
889        const float2 tmp = dst_fixup[(gridDim.x + bidx)*ncols + jc];
890
891        // Scale the current and new value accumulators depending on the max. values.
892        const float max_val_new = fmaxf(max_val, tmp.x);
893
894        const float diff_val = max_val - max_val_new;
895        const float diff_add = tmp.x   - max_val_new;
896
897        const float scale_val = diff_val >= SOFTMAX_FTZ_THRESHOLD ? expf(diff_val) : 0.0f;
898        const float scale_add = diff_add >= SOFTMAX_FTZ_THRESHOLD ? expf(diff_add) : 0.0f;
899
900        dst_val = scale_val*dst_val + scale_add*dst_add;
901        rowsum  = scale_val*rowsum  + scale_add*tmp.y;
902
903        max_val = max_val_new;
904
905        // If this block started in a previous tile we are done and don't need to combine additional partial results.
906        if (fastmodulo(kbc, fd_iter_k) == 0 || fastdiv(kbc, fd_iter_k) < tile_kbc0) {
907            break;
908        }
909        bidx--;
910        kbc_stop = kbc;
911    }
912
913    // Write back final result:
914    *dst = dst_val / rowsum;
915}
916
917template<int D> // D == head size
918__launch_bounds__(D, 1)
919static __global__ void flash_attn_combine_results(
920        const float  * VKQ_parts_ptr,
921        const float2 * VKQ_meta_ptr,
922        float * dst_ptr,
923        const int parallel_blocks) {
924    ggml_cuda_pdl_lc();
925    const float  * GGML_CUDA_RESTRICT VKQ_parts = VKQ_parts_ptr;
926    const float2 * GGML_CUDA_RESTRICT VKQ_meta  = VKQ_meta_ptr;
927    float        * GGML_CUDA_RESTRICT dst       = dst_ptr;
928    // Dimension 0: threadIdx.x
929    // Dimension 1: blockIdx.x
930    // Dimension 2: blockIdx.y
931    // Dimension 3: blockIdx.z
932    // Memory layout is permuted with [0, 2, 1, 3]
933
934    const int ne01 = gridDim.x;
935    const int ne02 = gridDim.y;
936
937    const int col      = blockIdx.x;
938    const int head     = blockIdx.y;
939    const int sequence = blockIdx.z;
940
941    const int j_dst_unrolled = (sequence*ne01 + col)*ne02 + head;
942
943    VKQ_parts += j_dst_unrolled * parallel_blocks*D;
944    VKQ_meta  += j_dst_unrolled * parallel_blocks;
945    dst       += j_dst_unrolled *                 D;
946
947    const int tid = threadIdx.x;
948    __builtin_assume(tid < D);
949
950    extern __shared__ float2 meta[];
951    ggml_cuda_pdl_sync();
952    for (int i = tid; i < 2*parallel_blocks; i += D) {
953        ((float *) meta)[i] = ((const float *)VKQ_meta) [i];
954    }
955
956    __syncthreads();
957
958    float kqmax = meta[0].x;
959    for (int l = 1; l < parallel_blocks; ++l) {
960        kqmax = max(kqmax, meta[l].x);
961    }
962
963    float VKQ_numerator   = 0.0f;
964    float VKQ_denominator = 0.0f;
965    for (int l = 0; l < parallel_blocks; ++l) {
966        const float KQ_max_scale = expf(meta[l].x - kqmax);
967
968        VKQ_numerator   += KQ_max_scale * VKQ_parts[l*D + tid];
969        VKQ_denominator += KQ_max_scale * meta[l].y;
970    }
971
972    dst[tid] = VKQ_numerator / VKQ_denominator;
973}
974
975template <int DV, int ncols1, int ncols2>
976void launch_fattn(
977    ggml_backend_cuda_context & ctx, ggml_tensor * dst, fattn_kernel_t fattn_kernel, const int nwarps, const size_t nbytes_shared,
978    const int nbatch_fa, const bool need_f16_K, const bool need_f16_V, const bool stream_k, const bool use_sparse,
979    const int warp_size = WARP_SIZE
980) {
981    constexpr int ncols = ncols1 * ncols2;
982
983    const ggml_tensor * Q = dst->src[0];
984    const ggml_tensor * K = dst->src[1];
985    const ggml_tensor * V = dst->src[2];
986
987    const bool V_is_K_view = V->view_src && (V->view_src == K || (V->view_src == K->view_src && V->view_offs == K->view_offs));
988
989    const ggml_tensor * mask  = dst->src[3];
990    const ggml_tensor * sinks = dst->src[4];
991
992    ggml_tensor * KQV = dst;
993
994    GGML_ASSERT(Q->type == GGML_TYPE_F32);
995    GGML_ASSERT(KQV->type == GGML_TYPE_F32);
996
997    GGML_ASSERT(Q->nb[0] == ggml_element_size(Q));
998    GGML_ASSERT(K->nb[0] == ggml_element_size(K));
999    GGML_ASSERT(V->nb[0] == ggml_element_size(V));
1000
1001    GGML_ASSERT(!mask || mask->type == GGML_TYPE_F16);
1002
1003    ggml_cuda_pool & pool = ctx.pool();
1004    cudaStream_t main_stream = ctx.stream();
1005    const int id  = ggml_cuda_get_device();
1006    const int cc  = ggml_cuda_info().devices[id].cc;
1007    const int nsm = ggml_cuda_info().devices[id].nsm;
1008
1009    const ggml_cuda_flash_attn_ext_f16_extra_data f16_extra =
1010        ggml_cuda_flash_attn_ext_get_f16_extra_data(KQV, need_f16_K, need_f16_V);
1011
1012    ggml_cuda_pool_alloc<int>    KV_max(pool);
1013    ggml_cuda_pool_alloc<float>  dst_tmp(pool);
1014    ggml_cuda_pool_alloc<float2> dst_tmp_meta(pool);
1015
1016    const char * K_data = (const char *) K->data;
1017    size_t nb11 = K->nb[1];
1018    size_t nb12 = K->nb[2];
1019    size_t nb13 = K->nb[3];
1020
1021    const char * V_data = (const char *) V->data;
1022    size_t nb21 = V->nb[1];
1023    size_t nb22 = V->nb[2];
1024    size_t nb23 = V->nb[3];
1025
1026    if (need_f16_K && K->type != GGML_TYPE_F16) {
1027        const size_t bs = ggml_blck_size(K->type);
1028        const size_t ts = ggml_type_size(K->type);
1029
1030        GGML_ASSERT(f16_extra.K != 0);
1031        half * K_f16 = (half *) f16_extra.K;
1032        if (ggml_is_contiguously_allocated(K)) {
1033            to_fp16_cuda_t to_fp16 = ggml_get_to_fp16_cuda(K->type);
1034            to_fp16(K_data, K_f16, ggml_nelements(K), main_stream);
1035
1036            nb11 = nb11*bs*sizeof(half)/ts;
1037            nb12 = nb12*bs*sizeof(half)/ts;
1038            nb13 = nb13*bs*sizeof(half)/ts;
1039        } else {
1040            GGML_ASSERT(K->nb[0] == ts);
1041            to_fp16_nc_cuda_t to_fp16 = ggml_get_to_fp16_nc_cuda(K->type);
1042            const int64_t s01 = nb11 / ts;
1043            const int64_t s02 = nb12 / ts;
1044            const int64_t s03 = nb13 / ts;
1045            to_fp16(K_data, K_f16, K->ne[0], K->ne[1], K->ne[2], K->ne[3], s01, s02, s03, main_stream);
1046
1047            nb11 = K->ne[0] * sizeof(half);
1048            nb12 = K->ne[1] * nb11;
1049            nb13 = K->ne[2] * nb12;
1050        }
1051        K_data = (char *) K_f16;
1052    }
1053
1054    if (need_f16_V && V->type != GGML_TYPE_F16) {
1055        if (V_is_K_view) {
1056            V_data = K_data;
1057            nb21   = nb11;
1058            nb22   = nb12;
1059            nb23   = nb13;
1060        } else {
1061            const size_t bs = ggml_blck_size(V->type);
1062            const size_t ts = ggml_type_size(V->type);
1063
1064            GGML_ASSERT(f16_extra.V != 0);
1065            half * V_f16 = (half *) f16_extra.V;
1066            if (ggml_is_contiguously_allocated(V)) {
1067                to_fp16_cuda_t to_fp16 = ggml_get_to_fp16_cuda(V->type);
1068                to_fp16(V_data, V_f16, ggml_nelements(V), main_stream);
1069                V_data = (char *) V_f16;
1070
1071                nb21 = nb21*bs*sizeof(half)/ts;
1072                nb22 = nb22*bs*sizeof(half)/ts;
1073                nb23 = nb23*bs*sizeof(half)/ts;
1074            } else {
1075                GGML_ASSERT(V->nb[0] == ts);
1076                to_fp16_nc_cuda_t to_fp16 = ggml_get_to_fp16_nc_cuda(V->type);
1077                const int64_t s01 = nb21 / ts;
1078                const int64_t s02 = nb22 / ts;
1079                const int64_t s03 = nb23 / ts;
1080                to_fp16(V_data, V_f16, V->ne[0], V->ne[1], V->ne[2], V->ne[3], s01, s02, s03, main_stream);
1081
1082                nb21 = V->ne[0] * sizeof(half);
1083                nb22 = V->ne[1] * nb21;
1084                nb23 = V->ne[2] * nb22;
1085            }
1086            V_data = (char *) V_f16;
1087        }
1088    }
1089
1090    const int ntiles_x     = ((Q->ne[1] + ncols1 - 1) / ncols1);
1091    const int gqa_ratio    = Q->ne[2] / K->ne[2];
1092    const int ntiles_z_gqa = ((gqa_ratio + ncols2 - 1) / ncols2);
1093    const int ntiles_dst   = ntiles_x * ntiles_z_gqa * K->ne[2] * Q->ne[3];
1094
1095    const int32_t n_kv_max = use_sparse ? ggml_get_op_params_i32(KQV, 4) : 0;
1096    if (use_sparse) {
1097        GGML_ASSERT(mask != nullptr);
1098        GGML_ASSERT(n_kv_max > 0);
1099        const size_t mask_rows = size_t(mask->ne[1]) * mask->ne[3];
1100
1101        KV_max.alloc(size_t(n_kv_max) * mask_rows);
1102        ggml_cuda_flash_attn_ext_compact_mask(mask, KV_max.ptr, n_kv_max, main_stream);
1103    }
1104
1105    // Optional optimization where the mask is scanned to determine whether part of the calculation can be skipped.
1106    // Only worth the overhead if there is at lease one FATTN_KQ_STRIDE x FATTN_KQ_STRIDE square to be skipped or
1107    //     multiple sequences of possibly different lengths.
1108    if (!use_sparse && mask && K->ne[1] % FATTN_KQ_STRIDE == 0 && (Q->ne[1] >= 1024 || Q->ne[3] > 1)) {
1109        const int64_t s31 = mask->nb[1] / sizeof(half2);
1110        const int64_t s33 = mask->nb[3] / sizeof(half2);
1111
1112        const dim3 blocks_num_KV_max(ntiles_x, Q->ne[3], 1);
1113        const dim3 block_dim_KV_max(FATTN_KQ_STRIDE/2, 1, 1);
1114
1115        const int ne_KV_max = blocks_num_KV_max.x*blocks_num_KV_max.y;
1116        const int iter_k = K->ne[1] / FATTN_KQ_STRIDE;
1117
1118        KV_max.alloc(ne_KV_max);
1119        ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(blocks_num_KV_max, block_dim_KV_max, 0, main_stream);
1120        ggml_cuda_kernel_launch(flash_attn_mask_to_KV_max<ncols1>, launch_params,
1121            (const half2 *) mask->data, KV_max.ptr, iter_k, s31, s33);
1122        CUDA_CHECK(cudaGetLastError());
1123    }
1124
1125    const dim3 block_dim(warp_size, nwarps, 1);
1126    int max_blocks_per_sm = 1; // Max. number of active blocks limited by occupancy.
1127    CUDA_CHECK(cudaOccupancyMaxActiveBlocksPerMultiprocessor(&max_blocks_per_sm, fattn_kernel, block_dim.x * block_dim.y * block_dim.z, nbytes_shared));
1128    GGML_ASSERT(max_blocks_per_sm > 0);
1129    int parallel_blocks = max_blocks_per_sm;
1130
1131    const int64_t n_kv = use_sparse ? n_kv_max : K->ne[1];
1132    const int ntiles_KV = (n_kv + nbatch_fa - 1) / nbatch_fa; // Max. number of parallel blocks limited by KV cache length.
1133
1134    dim3 blocks_num;
1135    if (stream_k) {
1136        auto should_use_stream_k = [](const int cc, const int ntiles_dst, const int max_blocks, const int DKQ) {
1137            const int tiles_nwaves             = (ntiles_dst + max_blocks - 1) / max_blocks;
1138            const int tiles_efficiency_percent = 100 * ntiles_dst / (max_blocks*tiles_nwaves);
1139
1140            if (GGML_CUDA_CC_IS_NVIDIA(cc) && cc >= GGML_CUDA_CC_ADA_LOVELACE) {
1141                return true;
1142            }
1143            if (amd_wmma_available(cc) && DKQ == 64) {
1144                return true; // TODO better configuration
1145            }
1146            return tiles_efficiency_percent < 75;
1147        };
1148
1149        const int  max_blocks   = max_blocks_per_sm*nsm;
1150        const bool use_stream_k = should_use_stream_k(cc, ntiles_dst, max_blocks, Q->ne[0]);
1151
1152        blocks_num.x = ntiles_dst;
1153        blocks_num.y = 1;
1154        blocks_num.z = 1;
1155
1156        if(use_stream_k) {
1157            const int nblocks_stream_k_raw = std::min(max_blocks, ntiles_KV*ntiles_dst);
1158            // Round down to a multiple of ntiles_dst so that each output tile gets the same number of blocks (avoids fixup).
1159            // Only do this if the occupancy loss from rounding is acceptable.
1160            const int nblocks_stream_k_rounded = (nblocks_stream_k_raw / ntiles_dst) * ntiles_dst;
1161            const int max_efficiency_loss_percent = 5;
1162            const int efficiency_loss_percent = nblocks_stream_k_rounded > 0
1163                ? 100 * (nblocks_stream_k_raw - nblocks_stream_k_rounded) / nblocks_stream_k_raw
1164                : 100;
1165            const int nblocks_stream_k = efficiency_loss_percent <= max_efficiency_loss_percent
1166                ? nblocks_stream_k_rounded
1167                : nblocks_stream_k_raw;
1168
1169            blocks_num.x = nblocks_stream_k;
1170        }
1171
1172        if (ntiles_dst % blocks_num.x != 0) { // Fixup is only needed if the SMs work on fractional tiles.
1173            dst_tmp_meta.alloc((size_t(blocks_num.x) * ncols * (2 + DV/2)));
1174        }
1175    } else {
1176        // parallel_blocks must not be larger than what the tensor size allows:
1177        parallel_blocks = std::min(parallel_blocks, ntiles_KV);
1178
1179        // If ntiles_total % blocks_per_wave != 0 then some efficiency is lost due to tail effects.
1180        // Test whether parallel_blocks can be set to a higher value for better efficiency.
1181        const int blocks_per_wave = nsm * max_blocks_per_sm;
1182        int nwaves_best = 0;
1183        int efficiency_percent_best = 0;
1184        for (int parallel_blocks_test = parallel_blocks; parallel_blocks_test <= ntiles_KV; ++parallel_blocks_test) {
1185            const int nblocks_total = ntiles_dst * parallel_blocks_test;
1186            const int nwaves = (nblocks_total + blocks_per_wave - 1) / blocks_per_wave;
1187            const int efficiency_percent = 100 * nblocks_total / (nwaves*blocks_per_wave);
1188
1189            // Stop trying configurations with more waves if we already have good efficiency to avoid excessive overhead.
1190            if (efficiency_percent_best >= 95 && nwaves > nwaves_best) {
1191                break;
1192            }
1193
1194            if (efficiency_percent > efficiency_percent_best) {
1195                nwaves_best = nwaves;
1196                efficiency_percent_best = efficiency_percent;
1197                parallel_blocks = parallel_blocks_test;
1198            }
1199        }
1200
1201        blocks_num.x = ntiles_x;
1202        blocks_num.y = parallel_blocks;
1203        blocks_num.z = ntiles_z_gqa*K->ne[2]*Q->ne[3];
1204
1205        if (parallel_blocks > 1) {
1206            dst_tmp.alloc(parallel_blocks*ggml_nelements(KQV));
1207            dst_tmp_meta.alloc(parallel_blocks*ggml_nrows(KQV));
1208        }
1209    }
1210
1211    float scale         = 1.0f;
1212    float max_bias      = 0.0f;
1213    float logit_softcap = 0.0f;
1214
1215    memcpy(&scale,         (const float *) KQV->op_params + 0, sizeof(float));
1216    memcpy(&max_bias,      (const float *) KQV->op_params + 1, sizeof(float));
1217    memcpy(&logit_softcap, (const float *) KQV->op_params + 2, sizeof(float));
1218
1219    if (logit_softcap != 0.0f) {
1220        scale /= logit_softcap;
1221    }
1222
1223    const uint32_t n_head      = Q->ne[2];
1224    const uint32_t n_head_log2 = 1u << uint32_t(floorf(log2f(float(n_head))));
1225
1226    const float m0 = powf(2.0f, -(max_bias       ) / n_head_log2);
1227    const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2);
1228
1229    // TODO other tensor dimensions after removal of WMMA kernel:
1230    const uint3 ne01 = init_fastdiv_values(Q->ne[1]);
1231
1232    GGML_ASSERT(block_dim.x % warp_size == 0);
1233
1234        ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(blocks_num, block_dim, nbytes_shared, main_stream);
1235        ggml_cuda_kernel_launch(fattn_kernel, launch_params,
1236        (const char *) Q->data,
1237        K_data,
1238        V_data,
1239        mask ? ((const char *) mask->data) : nullptr,
1240        sinks ? ((const char *) sinks->data) : nullptr,
1241        KV_max.ptr,
1242        !stream_k && parallel_blocks > 1 ? dst_tmp.ptr : (float *) KQV->data, dst_tmp_meta.ptr,
1243        scale, max_bias, m0, m1, n_head_log2, logit_softcap,
1244        Q->ne[0], ne01,     Q->ne[2], Q->ne[3], Q->nb[1], Q->nb[2], Q->nb[3],
1245        K->ne[0], n_kv, K->ne[2], K->ne[3], nb11, nb12, nb13,
1246        nb21, nb22, nb23,
1247        mask ? mask->ne[1] : 0, mask ? mask->ne[2] : 0, mask ? mask->ne[3] : 0,
1248        mask ? mask->nb[1] : 0, mask ? mask->nb[2] : 0, mask ? mask->nb[3] : 0
1249    );
1250    CUDA_CHECK(cudaGetLastError());
1251
1252    if (stream_k) {
1253        if ((int)blocks_num.x % ntiles_dst == 0 && (int)blocks_num.x > ntiles_dst) {
1254            // Optimized fixup: nblocks_stream_k is a multiple of ntiles_dst, launch one block per tile.
1255            const int nblocks_sk  = (int)blocks_num.x;
1256            const int bpt         = nblocks_sk / ntiles_dst;
1257
1258            const uint3 fd0 = init_fastdiv_values(ntiles_x * ntiles_z_gqa * K->ne[2]);
1259            const uint3 fd1 = init_fastdiv_values(ntiles_x * ntiles_z_gqa);
1260            const uint3 fd2 = init_fastdiv_values(ntiles_x);
1261
1262            const dim3 block_dim_combine(DV, 1, 1);
1263            const dim3 blocks_num_combine = {(unsigned)ntiles_dst, ncols1, ncols2};
1264
1265            const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(blocks_num_combine, block_dim_combine, 0, main_stream);
1266            ggml_cuda_kernel_launch(flash_attn_stream_k_fixup_uniform<DV, ncols1, ncols2>, launch_params,
1267                (float *) KQV->data, dst_tmp_meta.ptr,
1268                 Q->ne[1], Q->ne[2], K->ne[2], nblocks_sk,
1269                 gqa_ratio, bpt, fd0, fd1, fd2);
1270        } else if (ntiles_dst % blocks_num.x != 0) {
1271            // General fixup for the cases where nblocks_stream_k < ntiles_dst.
1272            const int total_work = ntiles_KV * ntiles_dst;
1273
1274            const uint3 fd_k_j_z_ne12 = init_fastdiv_values(ntiles_KV * ntiles_x * ntiles_z_gqa * K->ne[2]);
1275            const uint3 fd_k_j_z      = init_fastdiv_values(ntiles_KV * ntiles_x * ntiles_z_gqa);
1276            const uint3 fd_k_j        = init_fastdiv_values(ntiles_KV * ntiles_x);
1277            const uint3 fd_k          = init_fastdiv_values(ntiles_KV);
1278
1279            const dim3 block_dim_combine(DV, 1, 1);
1280            const dim3 blocks_num_combine = {blocks_num.x, ncols1, ncols2};
1281
1282            const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(blocks_num_combine, block_dim_combine, 0, main_stream);
1283            ggml_cuda_kernel_launch(flash_attn_stream_k_fixup_general<DV, ncols1, ncols2>, launch_params,
1284                (float *) KQV->data, dst_tmp_meta.ptr,
1285                 Q->ne[1], Q->ne[2], gqa_ratio, total_work,
1286                 fd_k_j_z_ne12, fd_k_j_z, fd_k_j, fd_k);
1287        }
1288    } else if (parallel_blocks > 1) {
1289        const dim3 block_dim_combine(DV, 1, 1);
1290        const dim3 blocks_num_combine(Q->ne[1], Q->ne[2], Q->ne[3]);
1291        const size_t nbytes_shared_combine = parallel_blocks*sizeof(float2);
1292
1293        const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(blocks_num_combine, block_dim_combine, nbytes_shared_combine, main_stream);
1294        ggml_cuda_kernel_launch(flash_attn_combine_results<DV>, launch_params,
1295            dst_tmp.ptr, dst_tmp_meta.ptr, (float *) KQV->data, parallel_blocks);
1296    }
1297    CUDA_CHECK(cudaGetLastError());
1298}