char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
b54cb2e3d
char/aliceai-t5-moe
1#include <sycl/sycl.hpp> 2#include <sycl/ext/oneapi/work_group_static.hpp> 3#include "dpct/helper.hpp" 4#include "common.hpp" 5#include "fattn-common.hpp" 6 7#include <cmath> 8#include <float.h> 9 10namespace syclex= sycl::ext::oneapi::experimental; 11 12#define GGML_SYCL_FATTN_TILE_CONFIG_CASE (DKQ_ ,DV_ ,ncols_ ,nthreads ,occupancy ,nbatch_fa ,nbatch_K ) \ 13 if (DKQ == (DKQ_) && DV == (DV_) && ncols == (ncols_)) { \ 14 static_assert((nthreads) <= 512, "bad nthreads"); \ 15 static_assert((occupancy) <= 8, "bad occupancy"); \ 16 static_assert((nbatch_fa) <= 256, "bad nbatch_fa"); \ 17 static_assert((nbatch_K) <= 256, "bad nbatch_K"); \ 18 return ((nthreads) << 0) | ((occupancy) << 10) | ((nbatch_fa) << 14) | ((nbatch_K) << 23); \ 19 } \ 20 21static constexpr uint32_t ggml_sycl_fattn_tile_get_config_fp16 (const int DKQ ,const int DV ,const int ncols ) { 22GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,2 ,64 ,2 ,64 ,40 ) 23GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,4 ,128 ,2 ,64 ,40 ) 24GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,8 ,256 ,2 ,64 ,40 ) 25GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,16 ,256 ,2 ,64 ,40 ) 26GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,32 ,256 ,2 ,64 ,40 ) 27 28GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,2 ,64 ,2 ,64 ,64 ) 29GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,4 ,128 ,2 ,64 ,64 ) 30GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,8 ,256 ,2 ,64 ,64 ) 31GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,16 ,256 ,2 ,64 ,64 ) 32GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,32 ,256 ,2 ,64 ,64 ) 33 34GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,2 ,64 ,2 ,64 ,72 ) 35GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,4 ,128 ,2 ,64 ,72 ) 36GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,8 ,256 ,2 ,64 ,72 ) 37GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,16 ,256 ,2 ,64 ,72 ) 38GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,32 ,256 ,2 ,64 ,72 ) 39 40GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,2 ,64 ,2 ,64 ,40 ) 41GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,4 ,128 ,2 ,64 ,40 ) 42GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,8 ,256 ,2 ,64 ,40 ) 43GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,16 ,256 ,2 ,64 ,40 ) 44GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,32 ,256 ,2 ,64 ,40 ) 45 46GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,2 ,64 ,2 ,64 ,48 ) 47GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,4 ,128 ,2 ,64 ,48 ) 48GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,8 ,256 ,2 ,64 ,48 ) 49GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,16 ,256 ,2 ,64 ,48 ) 50GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,32 ,256 ,2 ,64 ,48 ) 51 52GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,2 ,64 ,2 ,64 ,56 ) 53GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,4 ,128 ,2 ,64 ,56 ) 54GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,8 ,256 ,2 ,64 ,56 ) 55GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,16 ,256 ,2 ,64 ,56 ) 56GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,32 ,256 ,2 ,64 ,56 ) 57 58GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,2 ,64 ,2 ,64 ,64 ) 59GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,4 ,128 ,2 ,64 ,64 ) 60GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,8 ,256 ,2 ,64 ,64 ) 61GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,16 ,256 ,2 ,64 ,64 ) 62GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,32 ,256 ,2 ,64 ,64 ) 63 64GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,2 ,64 ,2 ,64 ,64 ) 65GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,4 ,128 ,2 ,64 ,64 ) 66GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,8 ,256 ,2 ,64 ,64 ) 67GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,16 ,256 ,2 ,64 ,64 ) 68GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,32 ,256 ,2 ,64 ,64 ) 69 70GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,2 ,64 ,2 ,64 ,64 ) 71GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,4 ,128 ,2 ,64 ,64 ) 72GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,8 ,256 ,2 ,64 ,64 ) 73GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,16 ,256 ,2 ,64 ,64 ) 74GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,32 ,256 ,2 ,64 ,64 ) 75 76GGML_SYCL_FATTN_TILE_CONFIG_CASE (576 ,512 ,4 ,128 ,2 ,64 ,64 ) 77GGML_SYCL_FATTN_TILE_CONFIG_CASE (576 ,512 ,8 ,256 ,2 ,64 ,64 ) 78GGML_SYCL_FATTN_TILE_CONFIG_CASE (576 ,512 ,16 ,256 ,2 ,64 ,64 ) 79GGML_SYCL_FATTN_TILE_CONFIG_CASE (576 ,512 ,32 ,256 ,2 ,64 ,64 ) 80 81return 0 ; 82} 83 84static constexpr uint32_t ggml_sycl_fattn_tile_get_config_fp32 (const int DKQ ,const int DV ,const int ncols ) { 85GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,2 ,64 ,2 ,32 ,40 ) 86GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,4 ,128 ,2 ,32 ,40 ) 87GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,8 ,256 ,2 ,32 ,40 ) 88GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,16 ,256 ,2 ,32 ,40 ) 89GGML_SYCL_FATTN_TILE_CONFIG_CASE (40 ,40 ,32 ,256 ,2 ,32 ,40 ) 90 91GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,2 ,128 ,3 ,64 ,64 ) 92GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,4 ,128 ,3 ,32 ,64 ) 93GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,8 ,128 ,3 ,32 ,64 ) 94GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,16 ,128 ,3 ,64 ,64 ) 95GGML_SYCL_FATTN_TILE_CONFIG_CASE (64 ,64 ,32 ,256 ,2 ,64 ,64 ) 96 97GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,2 ,64 ,2 ,32 ,72 ) 98GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,4 ,128 ,2 ,32 ,72 ) 99GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,8 ,256 ,2 ,32 ,72 ) 100GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,16 ,256 ,2 ,32 ,72 ) 101GGML_SYCL_FATTN_TILE_CONFIG_CASE (72 ,72 ,32 ,256 ,2 ,32 ,72 ) 102 103GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,2 ,64 ,2 ,32 ,40 ) 104GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,4 ,128 ,2 ,32 ,40 ) 105GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,8 ,256 ,2 ,32 ,40 ) 106GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,16 ,256 ,2 ,32 ,40 ) 107GGML_SYCL_FATTN_TILE_CONFIG_CASE (80 ,80 ,32 ,256 ,2 ,32 ,40 ) 108 109GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,2 ,64 ,2 ,32 ,48 ) 110GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,4 ,128 ,2 ,32 ,48 ) 111GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,8 ,256 ,2 ,32 ,48 ) 112GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,16 ,256 ,2 ,32 ,48 ) 113GGML_SYCL_FATTN_TILE_CONFIG_CASE (96 ,96 ,32 ,256 ,2 ,32 ,48 ) 114 115GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,2 ,64 ,2 ,32 ,56 ) 116GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,4 ,128 ,2 ,32 ,56 ) 117GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,8 ,256 ,2 ,32 ,56 ) 118GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,16 ,256 ,2 ,32 ,56 ) 119GGML_SYCL_FATTN_TILE_CONFIG_CASE (112 ,112 ,32 ,256 ,2 ,32 ,56 ) 120 121GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,2 ,128 ,3 ,64 ,64 ) 122GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,4 ,128 ,3 ,32 ,128 ) 123GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,8 ,128 ,3 ,64 ,128 ) 124GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,16 ,128 ,3 ,32 ,128 ) 125GGML_SYCL_FATTN_TILE_CONFIG_CASE (128 ,128 ,32 ,256 ,2 ,64 ,64 ) 126 127GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,2 ,128 ,3 ,64 ,64 ) 128GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,4 ,128 ,3 ,32 ,64 ) 129GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,8 ,256 ,2 ,32 ,256 ) 130GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,16 ,256 ,2 ,32 ,128 ) 131GGML_SYCL_FATTN_TILE_CONFIG_CASE (256 ,256 ,32 ,256 ,2 ,32 ,64 ) 132 133GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,2 ,128 ,2 ,64 ,64 ) 134GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,4 ,128 ,2 ,64 ,64 ) 135GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,8 ,256 ,2 ,64 ,64 ) 136GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,16 ,256 ,2 ,64 ,64 ) 137GGML_SYCL_FATTN_TILE_CONFIG_CASE (512 ,512 ,32 ,256 ,2 ,64 ,64 ) 138 139GGML_SYCL_FATTN_TILE_CONFIG_CASE (576 ,512 ,4 ,128 ,2 ,32 ,64 ) 140GGML_SYCL_FATTN_TILE_CONFIG_CASE (576 ,512 ,8 ,256 ,2 ,32 ,64 ) 141GGML_SYCL_FATTN_TILE_CONFIG_CASE (576 ,512 ,16 ,256 ,2 ,32 ,64 ) 142 143return 0 ; 144} 145 146static constexpr uint32_t ggml_sycl_fattn_tile_get_config (const int DKQ ,const int DV ,const int ncols ,const int cc ) { 147if (fast_fp16_available (cc )) 148return ggml_sycl_fattn_tile_get_config_fp16 (DKQ ,DV ,ncols ); 149else 150return ggml_sycl_fattn_tile_get_config_fp32 (DKQ ,DV ,ncols ); 151} 152 153static constexpr uint32_t ggml_sycl_fattn_tile_get_config (const int DKQ ,const int DV ,const int ncols ) { 154#ifdef SYCL_FAST_FP16 155return ggml_sycl_fattn_tile_get_config_fp16 (DKQ ,DV ,ncols ); 156#else 157return ggml_sycl_fattn_tile_get_config_fp32 (DKQ ,DV ,ncols ); 158#endif // SYCL_FAST_FP16 159} 160 161static int ggml_sycl_fattn_tile_get_nthreads (const int DKQ ,const int DV ,const int ncols ,const int cc ) { 162return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ,cc ) >>0 )& ((1 <<10 )- 1 ); 163} 164 165static constexpr int ggml_sycl_fattn_tile_get_nthreads (const int DKQ ,const int DV ,const int ncols ) { 166return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ) >>0 )& ((1 <<10 )- 1 ); 167} 168 169static int ggml_sycl_fattn_tile_get_occupancy (const int DKQ ,const int DV ,const int ncols ,const int cc ) { 170return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ,cc ) >>10 )& ((1 <<4 )- 1 ); 171} 172 173static constexpr int ggml_sycl_fattn_tile_get_occupancy (const int DKQ ,const int DV ,const int ncols ) { 174return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ) >>10 )& ((1 <<4 )- 1 ); 175} 176 177static int ggml_sycl_fattn_tile_get_nbatch_fa (const int DKQ ,const int DV ,const int ncols ,const int cc ) { 178return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ,cc ) >>14 )& ((1 <<9 )- 1 ); 179} 180 181static constexpr int ggml_sycl_fattn_tile_get_nbatch_fa (const int DKQ ,const int DV ,const int ncols ) { 182return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ) >>14 )& ((1 <<9 )- 1 ); 183} 184 185static int ggml_sycl_fattn_tile_get_nbatch_K (const int DKQ ,const int DV ,const int ncols ,const int cc ) { 186return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ,cc ) >>23 )& ((1 <<9 )- 1 ); 187} 188 189static constexpr int ggml_sycl_fattn_tile_get_nbatch_K (const int DKQ ,const int DV ,const int ncols ) { 190return (ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols ) >>23 )& ((1 <<9 )- 1 ); 191} 192 193template < int warp_size ,int nwarps ,int I ,int J ,int J_padding ,bool oob_check > 194static __dpct_inline__ void flash_attn_tile_load_tile (const sycl::half2 * const __restrict__KV , 195 sycl::half2 * const __restrict__tile_KV , 196const int stride_KV , 197const int i_sup ) { 198auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 199constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes (); 200constexpr int cpy_ne = cpy_nb /4 ; 201 202auto load = [& ] (const int n ) { 203const int stride_j = warp_size >>n ; 204 205if (stride_j == 0 ) { 206return ; 207 } 208 209const int j0_start = stride_j == warp_size ?0 : ((J /2 )/cpy_ne )- ((J /2 )/cpy_ne ) % (2 * stride_j ); 210const int j0_stop = ((J /2 )/cpy_ne )- ((J /2 )/cpy_ne ) % (1 * stride_j ); 211const int stride_i = warp_size /stride_j ; 212 213if (j0_start == j0_stop ) { 214return ; 215 } 216 217#pragma unroll 218for (int i0 = 0 ;i0 < I ;i0 += nwarps * stride_i ) { 219const int i = i0 + item_ct1 .get_local_id (1 )* stride_i + 220 (stride_j == warp_size ?0 :item_ct1 .get_local_id (2 ) /stride_j ); 221 222if (i0 + nwarps * stride_i <=I || i < I ) { 223#pragma unroll 224for (int j0 = j0_start ;j0 < j0_stop ;j0 += stride_j ) { 225const int j = j0 * cpy_ne + (stride_j == warp_size ?item_ct1 .get_local_id (2 ) : 226item_ct1 .get_local_id (2 ) %stride_j )* 227cpy_ne ; 228 229const __dpct_align__ (16 ) sycl::half2 zero [cpy_ne ]= { 230 {0.0f ,0.0f } 231 }; 232ggml_sycl_memcpy_1 < cpy_nb > ( 233tile_KV + i * (J /2 + J_padding )+ j , 234 !oob_check || i < i_sup ?KV + i * stride_KV + j :zero ); 235 } 236 } 237 } 238 }; 239// 1: max 64*16=512 bytes, 512 half 240// 2: max 32*16=512 bytes, 256 half 241// 3: max 16*16=256 bytes, 128 half 242// 4: max 8*16=128 bytes, 64 half 243// 5: max 4*16= 64 bytes, 32 half 244// 6: max 2*16= 32 bytes, 16 half 245// 7: max 1*16= 16 bytes, 8 half 246 static_assert(J %8 == 0 ,"bad J" ); 247 static_assert((J /2 ) %cpy_ne == 0 ,"bad J" ); 248ggml_sycl_unroll < 7 > {}(load ); 249} 250 251template < int warp_size ,int nwarps ,int I ,int J ,int J_padding ,bool oob_check > 252static __dpct_inline__ void flash_attn_tile_load_tile (const sycl::half2 * const __restrict__KV , 253float * const __restrict__tile_KV , 254const int stride_KV , 255const int i_sup ) { 256constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes (); 257constexpr int cpy_ne = cpy_nb /4 ; 258 259auto load = [& ] (const int n ) { 260auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 261const int stride_j = warp_size >>n ; 262 263if (stride_j == 0 ) { 264return ; 265 } 266 267const int j0_start = stride_j == warp_size ?0 : (J /cpy_ne )- (J /cpy_ne ) % (2 * stride_j ); 268const int j0_stop = (J /cpy_ne )- (J /cpy_ne ) % (1 * stride_j ); 269const int stride_i = warp_size /stride_j ; 270 271if (j0_start == j0_stop ) { 272return ; 273 } 274 275#pragma unroll 276for (int i0 = 0 ;i0 < I ;i0 += nwarps * stride_i ) { 277const int i = i0 + item_ct1 .get_local_id (1 )* stride_i + 278 (stride_j == warp_size ?0 :item_ct1 .get_local_id (2 ) /stride_j ); 279 280if (i0 + nwarps * stride_i <=I || i < I ) { 281#pragma unroll 282for (int j0 = j0_start ;j0 < j0_stop ;j0 += stride_j ) { 283const int j = j0 * (cpy_ne /2 )+ (stride_j == warp_size ?item_ct1 .get_local_id (2 ) : 284item_ct1 .get_local_id (2 ) %stride_j )* 285 (cpy_ne /2 ); 286 287const sycl::half2 zero [cpy_ne /2 ]= { 288 {0.0f ,0.0f } 289 }; 290__dpct_align__ (16 ) sycl::half2 tmp_h2 [cpy_ne /2 ]; 291ggml_sycl_memcpy_1 < sizeof (tmp_h2 )> ( 292tmp_h2 , !oob_check || i < i_sup ?KV + i * stride_KV + j :zero ); 293 294__dpct_align__ (16 ) sycl::float2 tmp_f2 [cpy_ne /2 ]; 295#pragma unroll 296for (int l = 0 ;l < cpy_ne /2 ;++ l ) { 297tmp_f2 [l ]= tmp_h2 [l ].template convert < float , sycl::rounding_mode::automatic > (); 298 } 299ggml_sycl_memcpy_1 < sizeof (tmp_f2 )> (tile_KV + i * (J + J_padding )+ 2 * j ,tmp_f2 ); 300 } 301 } 302 } 303 }; 304// 1: max 32*16=512 bytes, 128 float 305// 2: max 16*16=256 bytes, 64 float 306// 3: max 8*16=128 bytes, 32 float 307// 4: max 4*16= 64 bytes, 16 float 308// 5: max 2*16= 32 bytes, 8 float 309 static_assert(J %8 == 0 ,"bad J" ); 310 static_assert(J %cpy_ne == 0 ,"bad J" ); 311ggml_sycl_unroll < 5 > {}(load ); 312} 313 314// Function that performs a single iteration in for the KQ matrix multiplication: 315template < int warp_size , 316int nwarps , 317int ncols1 , 318int ncols2 , 319int DKQ , 320int nbatch_fa , 321int nbatch_K , 322bool use_logit_softcap , 323bool oob_check , 324typename T_vec_dot > 325static __dpct_inline__ void flash_attn_tile_iter_KQ (T_vec_dot * const Q_tmp , 326const sycl::half2 * const __restrict__K_h2 , 327T_vec_dot * const KV_tmp , 328const int stride_K2 , 329const int k_VKQ_0 , 330const int k_VKQ_sup , 331const int k_KQ_0 , 332float * KQ_acc ) { 333auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 334constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes (); 335constexpr int cpy_ne = cpy_nb /4 ; 336 337constexpr int ncols = ncols1 * ncols2 ; 338constexpr int cpw = ncols > nwarps ?ncols /nwarps :1 ;// Q columns per warp 339constexpr int np = nwarps > ncols ?nwarps /ncols :1 ;// number of parallel warps per Q column 340 341flash_attn_tile_load_tile < warp_size ,nwarps ,nbatch_fa ,nbatch_K ,cpy_ne ,oob_check > 342 (K_h2 + int64_t (k_VKQ_0 )* stride_K2 + k_KQ_0 /2 ,KV_tmp ,stride_K2 ,k_VKQ_sup ); 343item_ct1 .barrier (sycl::access::fence_space::local_space ); 344 345#ifdef SYCL_FAST_FP16 346 static_assert((nbatch_K /2 ) %cpy_ne == 0 ,"bad nbatch_K" ); 347#pragma unroll 348for (int k_KQ_1 = 0 ;k_KQ_1 < nbatch_K /2 ;k_KQ_1 += cpy_ne ) { 349__dpct_align__ (16 ) sycl::half2 K_k [nbatch_fa / (np * warp_size )][cpy_ne ]; 350__dpct_align__ (16 ) sycl::half2 Q_k [cpw ][cpy_ne ]; 351#else 352 static_assert(nbatch_K %cpy_ne == 0 ,"bad nbatch_K" ); 353#pragma unroll 354for (int k_KQ_1 = 0 ;k_KQ_1 < nbatch_K ;k_KQ_1 += cpy_ne ) { 355__dpct_align__ (16 )float K_k [nbatch_fa /(np * warp_size )][cpy_ne ]; 356__dpct_align__ (16 )float Q_k [cpw ][cpy_ne ]; 357#endif // SYCL_FAST_FP16 358 359#pragma unroll 360for (int i_KQ_0 = 0 ;i_KQ_0 < nbatch_fa ;i_KQ_0 += np * warp_size ) { 361const int i_KQ = i_KQ_0 + (item_ct1 .get_local_id (1 ) %np )* warp_size + item_ct1 .get_local_id (2 ); 362 363#ifdef SYCL_FAST_FP16 364ggml_sycl_memcpy_1 < cpy_nb > (& K_k [i_KQ_0 /(np * warp_size )],& KV_tmp [i_KQ * (nbatch_K /2 + cpy_ne )+ k_KQ_1 ]); 365#else 366ggml_sycl_memcpy_1 < cpy_nb > (& K_k [i_KQ_0 /(np * warp_size )],& KV_tmp [i_KQ * (nbatch_K + cpy_ne )+ k_KQ_1 ]); 367#endif // SYCL_FAST_FP16 368 } 369#pragma unroll 370for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 371const int jc = jc0 + (item_ct1 .get_local_id (1 ) /np )* cpw ; 372 373#ifdef SYCL_FAST_FP16 374ggml_sycl_memcpy_1 < cpy_nb > (& Q_k [jc0 ],& Q_tmp [jc * (DKQ /2 )+ k_KQ_0 /2 + k_KQ_1 ]); 375#else 376ggml_sycl_memcpy_1 < cpy_nb > (& Q_k [jc0 ],& Q_tmp [jc * DKQ + k_KQ_0 + k_KQ_1 ]); 377#endif // SYCL_FAST_FP16 378 } 379 380#pragma unroll 381for (int i_KQ_0 = 0 ;i_KQ_0 < nbatch_fa ;i_KQ_0 += np * warp_size ) { 382#pragma unroll 383for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 384#pragma unroll 385for (int k = 0 ;k < cpy_ne ;++ k ) { 386ggml_sycl_mad (KQ_acc [i_KQ_0 /(np * warp_size )* cpw + jc0 ],K_k [i_KQ_0 /(np * warp_size )][k ],Q_k [jc0 ][k ]); 387 } 388 } 389 } 390 } 391 392if (k_KQ_0 + nbatch_K < DKQ ) { 393item_ct1 .barrier (sycl::access::fence_space::local_space );// Sync not needed on last iteration. 394 } 395} 396 397// Function that performs a single iteration of the main loop over up to nbatch_fa tokens. 398template < int warp_size , 399int nwarps , 400int ncols1 , 401int ncols2 , 402int DKQ , 403int DV , 404int nbatch_fa , 405int nbatch_K , 406bool use_logit_softcap , 407bool oob_check , 408typename T_vec_dot , 409typename T_KQ , 410typename T_acc > 411/* 412The total declared local variable size in device function flash_attn_tile_iter exceeds 128 bytes and may cause high register pressure. Consult with your hardware vendor to find the total register size available and adjust the code, or use smaller sub-group size to avoid high register pressure. 413*/ 414static __dpct_inline__ void flash_attn_tile_iter (T_vec_dot * const Q_tmp , 415const sycl::half2 * const __restrict__K_h2 , 416const sycl::half2 * const __restrict__V_h2 , 417const sycl::half * const __restrict__mask , 418const sycl::uint3 ne01 , 419const float logit_softcap , 420const float slope , 421T_KQ * const KQ , 422T_vec_dot * const KV_tmp , 423const int stride_K2 , 424const int stride_V2 , 425const int stride_mask , 426float * const KQ_max , 427float * const KQ_sum , 428T_acc * const VKQ , 429const int k_VKQ_0 , 430const int k_VKQ_max , 431const int col_Q_0 , 432float * KQ_max_new_shared ) { 433auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 434constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes (); 435constexpr int cpy_ne = cpy_nb /4 ; 436 437constexpr int ncols = ncols1 * ncols2 ; 438constexpr int cpw = ncols > nwarps ?ncols /nwarps :1 ;// Q columns per warp 439constexpr int np = nwarps > ncols ?nwarps /ncols :1 ;// number of parallel warps per Q column 440 441constexpr int DVp = (DV + 2 * warp_size - 1 )& ~(2 * warp_size - 1 );// DV padded to multiple of 2*warp_size. 442 443#ifdef SYCL_FAST_FP16 444constexpr int KQ_cs = cpw < 2 * cpy_ne ?cpw :2 * cpy_ne ; 445#else 446constexpr int KQ_cs = cpw < 1 * cpy_ne ?cpw :1 * cpy_ne ; 447#endif // SYCL_FAST_FP16 448 static_assert(cpw %KQ_cs == 0 ,"bad KQ_cs" ); 449const int k_VKQ_sup = k_VKQ_max - k_VKQ_0 ;// k supremum, only smaller k values have valid KV data 450 451float KQ_max_new [cpw ]; 452#pragma unroll 453for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 454KQ_max_new [jc0 ]= KQ_max [jc0 ]; 455 } 456 457float KQ_acc [nbatch_fa /(np * warp_size )* cpw ]= {0.0f };// Accumulators for KQ matrix multiplication. 458 459// KQ = K @ Q matrix multiplication: 460constexpr int nbatch_K_last = DKQ %nbatch_K ; 461#pragma unroll 462for (int k_KQ_0 = 0 ;k_KQ_0 < DKQ - nbatch_K_last ;k_KQ_0 += nbatch_K ) { 463flash_attn_tile_iter_KQ < warp_size ,nwarps ,ncols1 ,ncols2 ,DKQ ,nbatch_fa ,nbatch_K ,use_logit_softcap ,oob_check > ( 464Q_tmp ,K_h2 ,KV_tmp ,stride_K2 ,k_VKQ_0 ,k_VKQ_sup ,k_KQ_0 ,KQ_acc ); 465 } 466if (nbatch_K_last > 0 ) { 467constexpr int k_KQ_0 = DKQ - nbatch_K_last ; 468flash_attn_tile_iter_KQ < warp_size ,nwarps ,ncols1 ,ncols2 ,DKQ ,nbatch_fa ,nbatch_K_last ,use_logit_softcap ,oob_check > ( 469Q_tmp ,K_h2 ,KV_tmp ,stride_K2 ,k_VKQ_0 ,k_VKQ_sup ,k_KQ_0 ,KQ_acc ); 470 } 471 472// Apply logit softcap + mask, update KQ_max: 473#pragma unroll 474for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 475const int j = fastmodulo (col_Q_0 + (jc0 + (item_ct1 .get_local_id (1 ) /np )* cpw ) /ncols2 ,ne01 ); 476 477#pragma unroll 478for (int i_KQ_0 = 0 ;i_KQ_0 < nbatch_fa ;i_KQ_0 += np * warp_size ) { 479const int i_KQ = i_KQ_0 + (item_ct1 .get_local_id (1 ) %np )* warp_size + item_ct1 .get_local_id (2 ); 480 481#if defined(SYCL_FAST_FP16 )&& !defined(GGML_SYCL_F16 ) 482// Without the v_dot2_f32_f16 instruction there is a higher risk of numerical overflow in the KQ calculation. 483// Therefore, scale down Q values and apply the inverse scale the FP32 KQ values afterwards again. 484KQ_acc [i_KQ_0 /(np * warp_size )* cpw + jc0 ] *=4.0f ; 485#endif // defined(SYCL_FAST_FP16) && !defined(GGML_SYCL_F16) 486 487if (use_logit_softcap ) { 488KQ_acc [(i_KQ_0 / (np * warp_size ))* cpw + jc0 ]= 489logit_softcap * sycl::tanh ((float )KQ_acc [(i_KQ_0 / (np * warp_size ))* cpw + jc0 ]); 490 } 491 492if (!oob_check || i_KQ < k_VKQ_sup ) { 493KQ_acc [(i_KQ_0 / (np * warp_size ))* cpw + jc0 ]+= 494 (ncols2 > 1 || mask ) ?slope * sycl::vec < sycl::half ,1 > (mask [j * stride_mask + k_VKQ_0 + i_KQ ]) 495 .convert < float , sycl::rounding_mode::automatic > ()[0 ] : 4960.0f ; 497 498KQ_max_new [jc0 ]= 499 sycl::fmax ((float )KQ_max_new [jc0 ], 500 (float ) (KQ_acc [(i_KQ_0 / (np * warp_size ))* cpw + jc0 ]+ FATTN_KQ_MAX_OFFSET )); 501 } 502 } 503 504KQ_max_new [jc0 ]= warp_reduce_max < warp_size > (KQ_max_new [jc0 ]); 505 } 506 507if constexpr (np == 1 ) { 508item_ct1 .barrier (sycl::access::fence_space::local_space ); 509 }else { 510 static_assert(cpw == 1 ,"bad cpw" ); 511 512if (item_ct1 .get_local_id (2 )== 0 ) { 513KQ_max_new_shared [item_ct1 .get_local_id (1 )]= KQ_max_new [0 ]; 514 } 515item_ct1 .barrier (sycl::access::fence_space::local_space ); 516KQ_max_new [0 ]= KQ_max_new_shared [(item_ct1 .get_local_id (1 )& ~(np - 1 ))+ item_ct1 .get_local_id (2 ) %np ]; 517KQ_max_new [0 ]= warp_reduce_max < np > (KQ_max_new [0 ]); 518 } 519 520// Calculate KQ softmax, write to shared KQ buffer, re-scale VKQ accumulators: 521#pragma unroll 522for (int jc0 = 0 ;jc0 < cpw ;jc0 += KQ_cs ) { 523#ifdef SYCL_FAST_FP16 524__dpct_align__ (16 ) sycl::half tmp [nbatch_fa / (np * warp_size )][KQ_cs ]; 525#else 526__dpct_align__ (16 )float tmp [nbatch_fa /(np * warp_size )][KQ_cs ]; 527#endif // SYCL_FAST_FP16 528 529#pragma unroll 530for (int jc1 = 0 ;jc1 < KQ_cs ;++ jc1 ) { 531const int jc = jc0 + jc1 ; 532 533const float KQ_max_scale = sycl::native::exp ((float ) (KQ_max [jc ]- KQ_max_new [jc ])); 534KQ_max [jc ]= KQ_max_new [jc ]; 535 536float KQ_sum_add = 0.0f ; 537#pragma unroll 538for (int i0 = 0 ;i0 < nbatch_fa ;i0 += np * warp_size ) { 539const float val = 540 !oob_check || i0 + (item_ct1 .get_local_id (1 ) %np )* warp_size + item_ct1 .get_local_id (2 )< 541static_cast < uint32_t > (k_VKQ_sup ) ? 542 sycl::native::exp ((float ) (KQ_acc [(i0 / (np * warp_size ))* cpw + jc ]- KQ_max [jc ])) : 5430.0f ; 544KQ_sum_add += val ; 545tmp [i0 /(np * warp_size )][jc1 ]= val ; 546 } 547KQ_sum [jc ]= KQ_sum [jc ]* KQ_max_scale + KQ_sum_add ; 548 549#ifdef SYCL_FAST_FP16 550const sycl::half2 KQ_max_scale_h2 = sycl::half2 (KQ_max_scale ,KQ_max_scale ); 551#pragma unroll 552for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size ) { 553VKQ [jc * ((DVp /2 )/warp_size )+ i0 /warp_size ].x () *=KQ_max_scale_h2 .x (); 554VKQ [jc * ((DVp /2 )/warp_size )+ i0 /warp_size ].y () *=KQ_max_scale_h2 .y (); 555 } 556#else 557#pragma unroll 558for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size ) { 559VKQ [jc * ((DVp /2 )/warp_size )+ i0 /warp_size ].x () *=KQ_max_scale ; 560VKQ [jc * ((DVp /2 )/warp_size )+ i0 /warp_size ].y () *=KQ_max_scale ; 561 } 562#endif // SYCL_FAST_FP16 563 } 564 565#pragma unroll 566for (int i0 = 0 ;i0 < nbatch_fa ;i0 += np * warp_size ) { 567const int i = i0 + (item_ct1 .get_local_id (1 ) %np )* warp_size + item_ct1 .get_local_id (2 ); 568 569ggml_sycl_memcpy_1 < sizeof (tmp [0 ])> ( 570KQ + (jc0 /KQ_cs + (item_ct1 .get_local_id (1 ) /np )* (cpw /KQ_cs ))* (nbatch_fa * KQ_cs )+ i * KQ_cs , 571tmp [i0 / (np * warp_size )]); 572 } 573 } 574 575// VKQ = V @ KQ matrix multiplication: 576 static_assert(DV <=DKQ ,"bad DV" ); 577 static_assert(DV %nbatch_K == 0 || (nbatch_K %3 == 0 && DV % (nbatch_K * 2 /3 )== 0 ),"bad nbatch_K" ); 578constexpr int nbatch_V = (DV %nbatch_K == 0 ?nbatch_K :nbatch_K * 2 /3 )* nbatch_fa /DV ;// Number of V columns that fit in SRAM for K. 579 static_assert(nbatch_fa %nbatch_V == 0 ,"bad nbatch_V" ); 580 static_assert(nbatch_V %np == 0 ,"bad nbatch_V" ); 581#pragma unroll 582for (int k0 = 0 ;k0 < nbatch_fa ;k0 += nbatch_V ) { 583flash_attn_tile_load_tile < warp_size ,nwarps ,nbatch_V ,DV ,0 ,oob_check > 584 (V_h2 + int64_t (k_VKQ_0 + k0 )* stride_V2 ,KV_tmp ,stride_V2 ,k_VKQ_sup - k0 ); 585item_ct1 .barrier (sycl::access::fence_space::local_space ); 586 587#ifdef SYCL_FAST_FP16 588#pragma unroll 589for (int k1 = 0 ;k1 < nbatch_V ;k1 += np ) { 590__dpct_align__ (16 ) sycl::half2 V_k [(DVp /2 ) /warp_size ]; 591__dpct_align__ (16 ) sycl::half2 KQ_k [cpw ]; 592 593constexpr int cpy_ne_D = cpy_ne /2 < (DVp /2 )/warp_size ?cpy_ne /2 : (DVp /2 )/warp_size ; 594#pragma unroll 595for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size * cpy_ne_D ) { 596ggml_sycl_memcpy_1 < cpy_ne_D * 4 > (& V_k [i0 /warp_size ], 597& KV_tmp [(k1 + item_ct1 .get_local_id (1 ) %np )* (DV /2 )+ i0 + 598item_ct1 .get_local_id (2 )* cpy_ne_D ]); 599 } 600#pragma unroll 601for (int jc_VKQ_0 = 0 ;jc_VKQ_0 < cpw ;jc_VKQ_0 += KQ_cs ) { 602const int jc_KQ = jc_VKQ_0 /KQ_cs + (item_ct1 .get_local_id (1 ) /np )* (cpw /KQ_cs ); 603 604__dpct_align__ (16 ) sycl::half tmp [KQ_cs ]; 605ggml_sycl_memcpy_1 < KQ_cs * sizeof (sycl::half )> ( 606& tmp ,KQ + jc_KQ * (nbatch_fa * KQ_cs )+ (k0 + k1 + item_ct1 .get_local_id (1 ) %np )* KQ_cs ); 607#pragma unroll 608for (int jc_VKQ_1 = 0 ;jc_VKQ_1 < KQ_cs ;++ jc_VKQ_1 ) { 609KQ_k [jc_VKQ_0 + jc_VKQ_1 ]= sycl::half2 (tmp [jc_VKQ_1 ]); 610 } 611 } 612 613#pragma unroll 614for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size ) { 615#pragma unroll 616for (int jc_VKQ_0 = 0 ;jc_VKQ_0 < cpw ;++ jc_VKQ_0 ) { 617VKQ [jc_VKQ_0 * ((DVp /2 )/warp_size )+ i0 /warp_size ].x ()+= 618V_k [i0 /warp_size ].x ()* KQ_k [jc_VKQ_0 ].x (); 619VKQ [jc_VKQ_0 * ((DVp /2 )/warp_size )+ i0 /warp_size ].y ()+= 620V_k [i0 /warp_size ].y ()* KQ_k [jc_VKQ_0 ].y (); 621 } 622 } 623 } 624#else 625#pragma unroll 626for (int k1 = 0 ;k1 < nbatch_V ;k1 += np ) { 627__dpct_align__ (16 ) sycl::float2 V_k [(DVp /2 )/warp_size ]; 628__dpct_align__ (16 )float KQ_k [cpw ]; 629 630constexpr int cpy_ne_D = cpy_ne < DVp /warp_size ?cpy_ne :DVp /warp_size ; 631#pragma unroll 632for (int i0 = 0 ;i0 < DVp ;i0 += warp_size * cpy_ne_D ) { 633ggml_sycl_memcpy_1 < cpy_ne_D * 4 > (& V_k [i0 /(2 * warp_size )],& KV_tmp [(k1 + item_ct1 .get_local_id (1 ) %np )* DV + i0 + item_ct1 .get_local_id (2 )* cpy_ne_D ]); 634 } 635#pragma unroll 636for (int jc_VKQ_0 = 0 ;jc_VKQ_0 < cpw ;jc_VKQ_0 += KQ_cs ) { 637const int jc_KQ = jc_VKQ_0 /KQ_cs + (item_ct1 .get_local_id (1 ) /np )* (cpw /KQ_cs ); 638 639ggml_sycl_memcpy_1 < KQ_cs * sizeof (float )> ( 640& KQ_k [jc_VKQ_0 ],KQ + jc_KQ * (nbatch_fa * KQ_cs )+ (k0 + k1 + item_ct1 .get_local_id (1 ) %np )* KQ_cs ); 641 } 642 643#pragma unroll 644for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size ) { 645#pragma unroll 646for (int jc_VKQ_0 = 0 ;jc_VKQ_0 < cpw ;++ jc_VKQ_0 ) { 647VKQ [jc_VKQ_0 * ((DVp /2 )/warp_size )+ i0 /warp_size ].x ()+= V_k [i0 /warp_size ].x ()* KQ_k [jc_VKQ_0 ]; 648VKQ [jc_VKQ_0 * ((DVp /2 )/warp_size )+ i0 /warp_size ].y ()+= V_k [i0 /warp_size ].y ()* KQ_k [jc_VKQ_0 ]; 649 } 650 } 651 } 652#endif // SYCL_FAST_FP16 653item_ct1 .barrier (sycl::access::fence_space::local_space ); 654 } 655} 656 657template < int DKQ ,int DV ,int ncols1 ,int ncols2 ,bool use_logit_softcap ,int warp_size > // D == head size 658/* 659The total declared local variable size in device function flash_attn_tile exceeds 128 bytes and may cause high register pressure. Consult with your hardware vendor to find the total register size available and adjust the code, or use smaller sub-group size to avoid high register pressure. 660*/ 661static void flash_attn_tile (const char * Q , 662const char * K , 663const char * V , 664const char * mask , 665const char * sinks , 666const int * KV_max , 667float * dst , 668 sycl::float2 * dst_meta , 669const float scale , 670const float max_bias , 671const float m0 , 672const float m1 , 673const uint32_t n_head_log2 , 674const float logit_softcap , 675const int32_t ne00 , 676const sycl::uint3 ne01 , 677const int32_t ne02 , 678const int32_t ne03 , 679const int32_t nb01 , 680const int32_t nb02 , 681const int32_t nb03 , 682const int32_t ne10 , 683const int32_t ne11 , 684const int32_t ne12 , 685const int32_t ne13 , 686const int32_t nb11 , 687const int32_t nb12 , 688const int64_t nb13 , 689const int32_t nb21 , 690const int32_t nb22 , 691const int64_t nb23 , 692const int32_t ne31 , 693const int32_t ne32 , 694const int32_t ne33 , 695const int32_t nb31 , 696const int32_t nb32 , 697const int64_t nb33 ) { 698#ifdef SYCL_FLASH_ATTN 699// Skip unused kernel variants for faster compilation: 700auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 701if ((use_logit_softcap && !(DV == 128 || DV == 256 ))) { 702GGML_UNUSED_VARS (Q ,K ,V ,mask ,sinks ,KV_max ,dst ,dst_meta ,scale , 703max_bias ,m0 ,m1 ,n_head_log2 ,logit_softcap , 704ne00 ,ne01 ,ne02 ,ne03 , 705nb01 ,nb02 ,nb03 , 706ne10 ,ne11 ,ne12 ,ne13 , 707nb11 ,nb12 ,nb13 , 708nb21 ,nb22 ,nb23 , 709ne31 ,ne32 ,ne33 , 710nb31 ,nb32 ,nb33 ); 711return ; 712 } 713 714 static_assert(ggml_sycl_fattn_tile_get_config (DKQ ,DV ,ncols1 * ncols2 )!= 0 ,"kernel config not defined" ); 715 716constexpr int ncols = ncols1 * ncols2 ; 717 718constexpr int nwarps = ggml_sycl_fattn_tile_get_nthreads (DKQ ,DV ,ncols1 * ncols2 ) /warp_size ; 719constexpr int nbatch_fa = ggml_sycl_fattn_tile_get_nbatch_fa (DKQ ,DV ,ncols1 * ncols2 ); 720constexpr int nbatch_K = ggml_sycl_fattn_tile_get_nbatch_K (DKQ ,DV ,ncols1 * ncols2 ); 721 722// In this kernel Q, K, V are matrices while i, j, k are matrix indices. 723 724const int col_Q_0 = item_ct1 .get_group (2 )* ncols1 ;// Index of the first Q column for this SYCL block to work on. 725 726const int sequence = item_ct1 .get_group (0 ) / (ne02 /ncols2 ); 727const int head0 = item_ct1 .get_group (0 )* ncols2 - sequence * ne02 ;// == item_ct1.get_group(0) % (ne02/ncols2) 728const int gqa_ratio = ne02 /ne12 ;// With grouped query attention there are > 1 Q matrices per K, V matrix. 729const float * Q_f = (const float * ) (Q + nb03 * sequence + nb02 * head0 ); 730const sycl::half2 * K_h2 = (const sycl::half2 * ) (K + nb13 * sequence + nb12 * (head0 /gqa_ratio )); 731const sycl::half2 * V_h2 = 732 (const sycl::half2 * ) (V + nb23 * sequence + nb22 * (head0 /gqa_ratio ));// K and V have same shape 733 734const sycl::half * maskh = mask ? (const sycl::half * ) (mask + nb33 * (sequence %ne33 )) :nullptr ; 735 736const int stride_K2 = nb11 /sizeof (sycl::half2 ); 737const int stride_V2 = nb21 /sizeof (sycl::half2 ); 738const int stride_mask = nb31 /sizeof (sycl::half ); 739 740const float slope = ncols2 == 1 ?get_alibi_slope (max_bias ,head0 ,n_head_log2 ,m0 ,m1 ) :1.0f ; 741 742constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes (); 743constexpr int cpy_ne = cpy_nb /4 ; 744 745constexpr int cpw = ncols > nwarps ?ncols /nwarps :1 ;// Q columns per warp. 746constexpr int np = nwarps > ncols ?nwarps /ncols :1 ;// Number of parallel warps per Q column. 747 748 static_assert(cpw == 1 || np == 1 ,"bad cpw / np" ); 749 static_assert(nbatch_fa % (np * warp_size )== 0 ,"nbatch_fa % (np*warp_size) != 0" ); 750 751constexpr int DKQp = (DKQ + 2 * warp_size - 1 )& ~(2 * warp_size - 1 );// DKQ padded to multiple of 2*warp_size. 752constexpr int DVp = (DV + 2 * warp_size - 1 )& ~(2 * warp_size - 1 );// DV padded to multiple of 2*warp_size. 753 754// Q_tmp == SRAM buffer to hold Q data for the entire lifetime of the kernel. 755// KV_tmp == SRAM buffer to hold fragments of K/V data while iterating over ne11. 756// KV_tmp is padded to avoid memory conflicts for K (cpy_ne) and OOB accesses for V (DVp-DV). 757// KQ == SRAM buffer to hold KQ fragments between KQ and VKQ matrix multiplications. 758// VKQ == Accumulators in registers for the final VKQ result. 759 760 761#ifdef SYCL_FAST_FP16 762constexpr size_t lsm_size1 = ncols * DKQ /2 ; 763constexpr size_t lsm_size2 = nbatch_fa * (nbatch_K /2 + cpy_ne )+ DVp - DV ; 764constexpr size_t lsm_size3 = ncols * nbatch_fa ; 765constexpr size_t lsm_size4 = nwarps ; 766 767constexpr size_t local_share_mem_size = lsm_size1 * sizeof (sycl::half2 )+ 768lsm_size2 * sizeof (sycl::half2 )+ 769lsm_size3 * sizeof (sycl::half )+ 770lsm_size4 * sizeof (float ); 771 772 syclex::work_group_static < char [local_share_mem_size ]> lsm ; 773 774 sycl::half2 * Q_tmp = (sycl::half2 * )& lsm ; 775 sycl::half2 * KV_tmp = (sycl::half2 * )(Q_tmp + lsm_size1 ); 776 sycl::half * KQ = (sycl::half * )(KV_tmp + lsm_size2 ); 777float * KQ_max_new_shared = (float * )(KQ + lsm_size3 ); 778 779__dpct_align__ (16 ) sycl::half2 VKQ [cpw * ((DVp /2 ) /warp_size )]= { 780 {0.0f ,0.0f } 781 }; 782#else 783constexpr size_t lsm_size1 = ncols * DKQ ; 784constexpr size_t lsm_size2 = nbatch_fa * (nbatch_K + cpy_ne )+ DVp - DV ; 785constexpr size_t lsm_size3 = ncols * nbatch_fa ; 786constexpr size_t lsm_size4 = nwarps ; 787 788constexpr size_t local_share_mem_size = (lsm_size1 + lsm_size2 + lsm_size3 + lsm_size4 )* sizeof (float ); 789 790 syclex::work_group_static < char [local_share_mem_size ]> lsm ; 791 792float * Q_tmp = (float * )& lsm ; 793float * KV_tmp = Q_tmp + lsm_size1 ; 794float * KQ = KV_tmp + lsm_size2 ; 795float * KQ_max_new_shared = KQ + lsm_size3 ; 796 797__dpct_align__ (16 ) sycl::float2 VKQ [cpw * ((DVp /2 )/warp_size )]= {{0.0f ,0.0f }}; 798 799 800#endif // SYCL_FAST_FP16 801 802float KQ_max [cpw ]= {}; 803 804#pragma unroll 805for (int j0 = 0 ;j0 < ncols ;j0 += nwarps ) { 806KQ_max [j0 /nwarps ]= - FLT_MAX /2.0f ; 807 } 808float KQ_sum [cpw ]= {0.0f }; 809 810// Load Q data, convert to FP16 if fast: 811#pragma unroll 812for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 813const int jc = jc0 + (item_ct1 .get_local_id (1 ) /np )* cpw ; 814 815const int j = jc /ncols2 ; 816const int c = jc %ncols2 ; 817 818constexpr int cpy_ne_D = cpy_ne < DKQp /warp_size ?cpy_ne :DKQp /warp_size ; 819 820#pragma unroll 821for (int i0 = 0 ;i0 < DKQp ;i0 += np * warp_size * cpy_ne_D ) { 822if (i0 + np * warp_size * cpy_ne_D <=DKQ || 823i0 + (item_ct1 .get_local_id (1 ) %np )* (warp_size * cpy_ne_D )+ item_ct1 .get_local_id (2 )* cpy_ne_D < 824DKQ ) { 825__dpct_align__ (16 )float tmp_f [cpy_ne_D ]= {0.0f }; 826ggml_sycl_memcpy_1 < sizeof (tmp_f )> ( 827tmp_f ,& Q_f [c * (nb02 /sizeof (float ))+ fastmodulo (col_Q_0 + j ,ne01 )* (nb01 /sizeof (float ))+ 828i0 + (item_ct1 .get_local_id (1 ) %np )* (warp_size * cpy_ne_D )+ 829item_ct1 .get_local_id (2 )* cpy_ne_D ]); 830 831#pragma unroll 832for (int i1 = 0 ;i1 < cpy_ne_D ;++ i1 ) { 833tmp_f [i1 ] *=scale ; 834 } 835 836#ifdef SYCL_FAST_FP16 837__dpct_align__ (16 ) sycl::half2 tmp_h2 [cpy_ne_D /2 ]; 838#pragma unroll 839for (int i1 = 0 ;i1 < cpy_ne_D ;i1 += 2 ) { 840tmp_h2 [i1 /2 ]= make_half2 (tmp_f [i1 + 0 ],tmp_f [i1 + 1 ]); 841#if defined(SYCL_FAST_FP16 )&& !defined(GGML_SYCL_F16 ) 842// Without the v_dot2_f32_f16 instruction there is a higher risk of numerical overflow in the KQ calculation. 843// Therefore, scale down Q values and apply the inverse scale the FP32 KQ values afterwards again. 844tmp_h2 [i1 /2 ] *= sycl::half2 (0.25f ,0.25f ); 845#endif // defined(SYCL_FAST_FP16) && !defined(GGML_SYCL_F16) 846 } 847ggml_sycl_memcpy_1 < sizeof (tmp_h2 )> ( 848& Q_tmp [jc * (DKQ /2 )+ i0 /2 + (item_ct1 .get_local_id (1 ) %np )* (warp_size * cpy_ne_D /2 )+ 849item_ct1 .get_local_id (2 )* (cpy_ne_D /2 )], 850tmp_h2 ); 851#else 852ggml_sycl_memcpy_1 < sizeof (tmp_f )> ( 853& Q_tmp [jc * DKQ + i0 + (item_ct1 .get_local_id (1 ) %np )* (warp_size * cpy_ne_D )+ item_ct1 .get_local_id (2 )* cpy_ne_D ], 854tmp_f ); 855#endif // SYCL_FAST_FP16 856 } 857 } 858 } 859 860item_ct1 .barrier (sycl::access::fence_space::local_space ); 861 862// Main loop over KV cache: 863const int k_VKQ_max = KV_max ?KV_max [sequence * item_ct1 .get_group_range (2 )+ item_ct1 .get_group (2 )] :ne11 ; 864if (ncols2 == 1 ) { 865// Branch with out-of-bounds checks. 866int k_VKQ_0 = item_ct1 .get_group (1 )* nbatch_fa ; 867while (k_VKQ_0 < k_VKQ_max - nbatch_fa ) { 868constexpr bool oob_check = false; 869flash_attn_tile_iter < warp_size ,nwarps ,ncols1 ,ncols2 ,DKQ ,DV ,nbatch_fa ,nbatch_K ,use_logit_softcap , 870oob_check > (Q_tmp ,K_h2 ,V_h2 ,maskh ,ne01 ,logit_softcap ,slope ,KQ ,KV_tmp ,stride_K2 , 871stride_V2 ,stride_mask ,KQ_max ,KQ_sum ,VKQ ,k_VKQ_0 ,k_VKQ_max ,col_Q_0 , 872KQ_max_new_shared ); 873k_VKQ_0 += item_ct1 .get_group_range (1 )* nbatch_fa ; 874 } 875if (k_VKQ_0 < k_VKQ_max ) { 876constexpr bool oob_check = true; 877flash_attn_tile_iter < warp_size ,nwarps ,ncols1 ,ncols2 ,DKQ ,DV ,nbatch_fa ,nbatch_K ,use_logit_softcap , 878oob_check > (Q_tmp ,K_h2 ,V_h2 ,maskh ,ne01 ,logit_softcap ,slope ,KQ ,KV_tmp ,stride_K2 , 879stride_V2 ,stride_mask ,KQ_max ,KQ_sum ,VKQ ,k_VKQ_0 ,k_VKQ_max ,col_Q_0 , 880KQ_max_new_shared ); 881 } 882 }else { 883// Branch without out-of-bounds checks. 884for (int k_VKQ_0 = item_ct1 .get_group (1 )* nbatch_fa ;k_VKQ_0 < k_VKQ_max ; 885k_VKQ_0 += item_ct1 .get_group_range (1 )* nbatch_fa ) { 886 887constexpr bool oob_check = false; 888flash_attn_tile_iter < warp_size ,nwarps ,ncols1 ,ncols2 ,DKQ ,DV ,nbatch_fa ,nbatch_K ,use_logit_softcap , 889oob_check > (Q_tmp ,K_h2 ,V_h2 ,maskh ,ne01 ,logit_softcap ,slope ,KQ ,KV_tmp ,stride_K2 , 890stride_V2 ,stride_mask ,KQ_max ,KQ_sum ,VKQ ,k_VKQ_0 ,k_VKQ_max ,col_Q_0 , 891KQ_max_new_shared ); 892 } 893 } 894 895#pragma unroll 896for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 897KQ_sum [jc0 ]= warp_reduce_sum < warp_size > (KQ_sum [jc0 ]); 898 } 899 900if constexpr (np > 1 ) { 901 static_assert(cpw == 1 ,"bad cpw" ); 902 static_assert(nbatch_fa * nbatch_K >=nwarps * DVp ,"KV_tmp too small" ); 903 904#ifdef SYCL_FAST_FP16 905 sycl::half2 * VKQ_combine = (sycl::half2 * )KV_tmp ; 906#else 907float * VKQ_combine = (float * )KV_tmp ; 908#endif // SYCL_FAST_FP16 909 910float * KQ_sum_combine = (float * )Q_tmp ; 911 912if (item_ct1 .get_local_id (1 ) %np != 0 ) { 913 914#ifdef SYCL_FAST_FP16 915constexpr int cpy_ne_D = cpy_ne < (DVp /2 )/warp_size ?cpy_ne : (DVp /2 )/warp_size ; 916#pragma unroll 917for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size * cpy_ne_D ) { 918ggml_sycl_memcpy_1 < cpy_ne_D * 4 > ( 919& VKQ_combine [item_ct1 .get_local_id (1 )* (DVp /2 )+ i0 + item_ct1 .get_local_id (2 )* cpy_ne_D ], 920& VKQ [i0 /warp_size ]); 921 } 922#else 923 924constexpr int cpy_ne_D = cpy_ne < DVp /warp_size ?cpy_ne :DVp /warp_size ; 925 926#pragma unroll 927for (int i0 = 0 ;i0 < DVp ;i0 += warp_size * cpy_ne_D ) { 928ggml_sycl_memcpy_1 < cpy_ne_D * 4 > ( 929& VKQ_combine [item_ct1 .get_local_id (1 )* DVp + i0 + item_ct1 .get_local_id (2 )* cpy_ne_D ], ((const float * )VKQ )+ i0 /warp_size ); 930 } 931#endif // SYCL_FAST_FP16 932 933if (item_ct1 .get_local_id (2 )== 0 ) { 934KQ_sum_combine [item_ct1 .get_local_id (1 )]= KQ_sum [0 ]; 935 } 936return ; 937 } 938 939item_ct1 .barrier (sycl::access::fence_space::local_space ); 940 941#pragma unroll 942for (int ip = 1 ;ip < np ;++ ip ) { 943#ifdef SYCL_FAST_FP16 944constexpr int cpy_ne_D = cpy_ne < (DVp /2 )/warp_size ?cpy_ne : (DVp /2 )/warp_size ; 945#pragma unroll 946for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size * cpy_ne_D ) { 947__dpct_align__ (16 ) sycl::half2 tmp [cpy_ne_D ]; 948ggml_sycl_memcpy_1 < cpy_ne_D * 4 > (tmp ,& VKQ_combine [(item_ct1 .get_local_id (1 )+ ip )* (DVp /2 )+ i0 + 949item_ct1 .get_local_id (2 )* cpy_ne_D ]); 950#pragma unroll 951for (int i1 = 0 ;i1 < cpy_ne_D ;++ i1 ) { 952VKQ [i0 /warp_size + i1 ]+= tmp [i1 ]; 953 } 954 } 955#else 956constexpr int cpy_ne_D = cpy_ne < DVp /warp_size ?cpy_ne :DVp /warp_size ; 957#pragma unroll 958for (int i0 = 0 ;i0 < DVp ;i0 += warp_size * cpy_ne_D ) { 959__dpct_align__ (16 )float tmp [cpy_ne_D ]; 960ggml_sycl_memcpy_1 < cpy_ne_D * 4 > (tmp ,& VKQ_combine [(item_ct1 .get_local_id (1 )+ ip )* DVp + i0 + item_ct1 .get_local_id (2 )* cpy_ne_D ]); 961#pragma unroll 962for (int i1 = 0 ;i1 < cpy_ne_D ;++ i1 ) { 963 ((float * )VKQ )[i0 /warp_size + i1 ]+= tmp [i1 ]; 964 } 965 } 966#endif // SYCL_FAST_FP16 967 968KQ_sum [0 ]+= KQ_sum_combine [item_ct1 .get_local_id (1 )+ ip ]; 969 } 970 } 971 972// Attention sink: adjust KQ max and sum only for the first of all parallel blocks: 973if (sinks && item_ct1 .get_group (1 )== 0 ) { 974#pragma unroll 975for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 976const int jc = jc0 + (item_ct1 .get_local_id (1 ) /np )* cpw ; 977const float sink = ((const float * )sinks )[head0 + jc %ncols2 ]; 978 979float KQ_max_new_j = sycl::fmax ((float )KQ_max [jc0 ],sink ); 980const float KQ_max_scale = sycl::native::exp ((float ) (KQ_max [jc0 ]- KQ_max_new_j )); 981KQ_max [jc0 ]= KQ_max_new_j ; 982 983const float val = sycl::native::exp ((float ) (sink - KQ_max [jc0 ])); 984KQ_sum [jc0 ]= KQ_sum [jc0 ]* KQ_max_scale + val ; 985 986#ifdef SYCL_FAST_FP16 987const sycl::half2 KQ_max_scale_h2 = sycl::half2 (KQ_max_scale ,KQ_max_scale ); 988#pragma unroll 989for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size ) { 990VKQ [jc0 * ((DVp /2 )/warp_size )+ i0 /warp_size ] *=KQ_max_scale_h2 ; 991 } 992#else 993#pragma unroll 994for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size ) { 995VKQ [jc0 * ((DVp /2 )/warp_size )+ i0 /warp_size ].x () *=KQ_max_scale ; 996VKQ [jc0 * ((DVp /2 )/warp_size )+ i0 /warp_size ].y () *=KQ_max_scale ; 997 } 998#endif // SYCL_FAST_FP16 999 } 1000 } 1001 1002// Write back results: 1003#pragma unroll 1004for (int jc0 = 0 ;jc0 < cpw ;++ jc0 ) { 1005const int jc = jc0 + (item_ct1 .get_local_id (1 ) /np )* cpw ; 1006 1007const int j = jc /ncols2 ; 1008const int c = jc %ncols2 ; 1009 1010if (ncols1 > 1 && col_Q_0 + j >=int (ne01 .z ())) { 1011return ; 1012 } 1013 1014const float scale = item_ct1 .get_group_range (1 )== 1 ?1.0f /KQ_sum [jc0 ] :1.0f ; 1015 1016const int j_dst_unrolled = 1017 ((sequence * int (ne01 .z ())+ col_Q_0 + j )* ne02 + head0 + c )* item_ct1 .get_group_range (1 )+ 1018item_ct1 .get_group (1 ); 1019 1020#ifdef SYCL_FAST_FP16 1021constexpr int cpy_ne_D = cpy_ne /2 < (DVp /2 )/warp_size ?cpy_ne /2 : (DVp /2 )/warp_size ; 1022#pragma unroll 1023for (int i0 = 0 ;i0 < DVp /2 ;i0 += warp_size * cpy_ne_D ) { 1024__dpct_align__ (16 ) sycl::float2 tmp [cpy_ne_D ]; 1025#pragma unroll 1026for (int i1 = 0 ;i1 < cpy_ne_D ;++ i1 ) { 1027tmp [i1 ]= VKQ [jc0 * ((DVp /2 ) /warp_size )+ i0 /warp_size + i1 ] 1028 .template convert < float , sycl::rounding_mode::automatic > (); 1029tmp [i1 ].x () *=scale ; 1030tmp [i1 ].y () *=scale ; 1031 } 1032if (i0 + warp_size * cpy_ne_D <=DV /2 || i0 + item_ct1 .get_local_id (2 )* cpy_ne_D < DV /2 ) { 1033ggml_sycl_memcpy_1 < sizeof (tmp )> ( 1034& dst [j_dst_unrolled * DV + 2 * i0 + item_ct1 .get_local_id (2 )* (2 * cpy_ne_D )],tmp ); 1035 } 1036 } 1037#else 1038constexpr int cpy_ne_D = cpy_ne < DVp /warp_size ?cpy_ne :DVp /warp_size ; 1039#pragma unroll 1040for (int i0 = 0 ;i0 < DVp ;i0 += warp_size * cpy_ne_D ) { 1041if (i0 + warp_size * cpy_ne_D <=DV || i0 + item_ct1 .get_local_id (2 )* cpy_ne_D < DV ) { 1042#pragma unroll 1043for (int i1 = 0 ;i1 < cpy_ne_D /2 ;++ i1 ) { 1044VKQ [jc0 * ((DVp /2 )/warp_size )+ i0 /(2 * warp_size )+ i1 ].x () *=scale ; 1045VKQ [jc0 * ((DVp /2 )/warp_size )+ i0 /(2 * warp_size )+ i1 ].y () *=scale ; 1046 } 1047ggml_sycl_memcpy_1 < cpy_ne_D * 4 > ( 1048& dst [j_dst_unrolled * DV + i0 + item_ct1 .get_local_id (2 )* cpy_ne_D ], 1049& VKQ [jc0 * ((DVp /2 )/warp_size )+ i0 /(2 * warp_size )]); 1050 } 1051 } 1052#endif // SYCL_FAST_FP16 1053 1054if (item_ct1 .get_group_range (1 )!= 1 && item_ct1 .get_local_id (2 )== 0 ) { 1055dst_meta [j_dst_unrolled ]= make_float2 (KQ_max [jc0 ],KQ_sum [jc0 ]); 1056 } 1057 } 1058#else 1059GGML_UNUSED_VARS (Q ,K ,V ,mask ,sinks ,KV_max ,dst ,dst_meta ,scale , 1060max_bias ,m0 ,m1 ,n_head_log2 ,logit_softcap , 1061ne00 ,ne01 ,ne02 ,ne03 , 1062nb01 ,nb02 ,nb03 , 1063ne10 ,ne11 ,ne12 ,ne13 , 1064nb11 ,nb12 ,nb13 , 1065nb21 ,nb22 ,nb23 , 1066ne31 ,ne32 ,ne33 , 1067nb31 ,nb32 ,nb33 ); 1068#endif // SYCL_FLASH_ATTN 1069} 1070 1071template < int DKQ ,int DV ,int ncols2 ,bool use_logit_softcap > 1072static void launch_fattn_tile_switch_ncols1 (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 1073const ggml_tensor * Q = dst -> src [0 ]; 1074 1075const int id = ggml_sycl_get_device (); 1076const int cc = ggml_sycl_info ().devices [id ].cc ; 1077const int warp_size = WARP_32_SIZE ;//can't support WARP_16_SIZE 1078 1079constexpr size_t nbytes_shared = 0 ; 1080 1081if (DV < 512 && Q -> ne [1 ]< 32 ) { 1082if constexpr (ncols2 <=32 ) { 1083if (Q -> ne [1 ]> 16 /ncols2 ) { 1084constexpr int cols_per_block = 32 ; 1085const int nwarps = ggml_sycl_fattn_tile_get_nthreads (DKQ ,DV ,cols_per_block ,cc ) /warp_size ; 1086const int nbatch_fa = ggml_sycl_fattn_tile_get_nbatch_fa (DKQ ,DV ,cols_per_block ,cc ); 1087launch_fattn < DV ,cols_per_block /ncols2 ,ncols2 , 1088flash_attn_tile < DKQ ,DV ,cols_per_block /ncols2 ,ncols2 ,use_logit_softcap ,warp_size > ,warp_size > 1089 (ctx ,dst ,nwarps ,nbytes_shared ,nbatch_fa , true, true, false); 1090return ; 1091 } 1092 } 1093if constexpr (ncols2 <=16 ) { 1094if (Q -> ne [1 ]> 8 /ncols2 ) { 1095constexpr int cols_per_block = 16 ; 1096const int nwarps = ggml_sycl_fattn_tile_get_nthreads (DKQ ,DV ,cols_per_block ,cc ) /warp_size ; 1097const int nbatch_fa = ggml_sycl_fattn_tile_get_nbatch_fa (DKQ ,DV ,cols_per_block ,cc ); 1098launch_fattn < DV ,cols_per_block /ncols2 ,ncols2 , 1099flash_attn_tile < DKQ ,DV ,cols_per_block /ncols2 ,ncols2 ,use_logit_softcap ,warp_size > ,warp_size > 1100 (ctx ,dst ,nwarps ,nbytes_shared ,nbatch_fa , true, true, false); 1101return ; 1102 } 1103 } 1104if constexpr (ncols2 <=8 ) { 1105if (Q -> ne [1 ]> 4 /ncols2 ) { 1106constexpr int cols_per_block = 8 ; 1107const int nwarps = ggml_sycl_fattn_tile_get_nthreads (DKQ ,DV ,cols_per_block ,cc ) /warp_size ; 1108const int nbatch_fa = ggml_sycl_fattn_tile_get_nbatch_fa (DKQ ,DV ,cols_per_block ,cc ); 1109launch_fattn < DV ,cols_per_block /ncols2 ,ncols2 , 1110flash_attn_tile < DKQ ,DV ,cols_per_block /ncols2 ,ncols2 ,use_logit_softcap ,warp_size > ,warp_size > 1111 (ctx ,dst ,nwarps ,nbytes_shared ,nbatch_fa , true, true, false); 1112return ; 1113 } 1114 } 1115 } 1116 1117if constexpr (ncols2 <=4 ) { 1118if (Q -> ne [1 ]> 2 /ncols2 ) { 1119constexpr int cols_per_block = 4 ; 1120const int nwarps = ggml_sycl_fattn_tile_get_nthreads (DKQ ,DV ,cols_per_block ,cc ) /warp_size ; 1121const int nbatch_fa = ggml_sycl_fattn_tile_get_nbatch_fa (DKQ ,DV ,cols_per_block ,cc ); 1122launch_fattn < DV ,cols_per_block /ncols2 ,ncols2 , 1123flash_attn_tile < DKQ ,DV ,cols_per_block /ncols2 ,ncols2 ,use_logit_softcap ,warp_size > ,warp_size > 1124 (ctx ,dst ,nwarps ,nbytes_shared ,nbatch_fa , true, true, false); 1125return ; 1126 } 1127 } 1128 1129if constexpr (ncols2 <=2 ) { 1130constexpr int cols_per_block = 2 ; 1131const int nwarps = ggml_sycl_fattn_tile_get_nthreads (DKQ ,DV ,cols_per_block ,cc ) /warp_size ; 1132const int nbatch_fa = ggml_sycl_fattn_tile_get_nbatch_fa (DKQ ,DV ,cols_per_block ,cc ); 1133launch_fattn < DV ,cols_per_block /ncols2 ,ncols2 , 1134flash_attn_tile < DKQ ,DV ,cols_per_block /ncols2 ,ncols2 ,use_logit_softcap ,warp_size > ,warp_size > 1135 (ctx ,dst ,nwarps ,nbytes_shared ,nbatch_fa , true, true, false); 1136return ; 1137 } 1138 1139 { 1140constexpr int cols_per_block = ncols2 * 2 ; 1141const int nwarps = ggml_sycl_fattn_tile_get_nthreads (DKQ ,DV ,cols_per_block ,cc ) /warp_size ; 1142const int nbatch_fa = ggml_sycl_fattn_tile_get_nbatch_fa (DKQ ,DV ,cols_per_block ,cc ); 1143launch_fattn < DV ,cols_per_block /ncols2 ,ncols2 , 1144flash_attn_tile < DKQ ,DV ,cols_per_block /ncols2 ,ncols2 ,use_logit_softcap ,warp_size > ,warp_size > 1145 (ctx ,dst ,nwarps ,nbytes_shared ,nbatch_fa , true, true, false); 1146return ; 1147 } 1148 1149GGML_ABORT ("fatal error" ); 1150} 1151 1152template < int DKQ ,int DV ,bool use_logit_softcap > 1153static void launch_fattn_tile_switch_ncols2 (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 1154const ggml_tensor * KQV = dst ; 1155const ggml_tensor * Q = dst -> src [0 ]; 1156const ggml_tensor * K = dst -> src [1 ]; 1157const ggml_tensor * mask = dst -> src [3 ]; 1158 1159float max_bias = 0.0f ; 1160memcpy (& max_bias , (const float * )KQV -> op_params + 1 ,sizeof (float )); 1161 1162GGML_ASSERT (Q -> ne [2 ] %K -> ne [2 ]== 0 ); 1163const int gqa_ratio = Q -> ne [2 ] /K -> ne [2 ]; 1164 1165// On NVIDIA (Pascal and older) the GQA optimizations seem to be detrimental in some cases. 1166// However, for DKQ == 576, DV == 512 only the kernel variant with GQA optimizations is implemented. 1167//const bool nvidia = GGML_SYCL_CC_IS_NVIDIA(ggml_sycl_info().devices[ggml_sycl_get_device()].cc); 1168const int gqa_limit = gqa_ratio <=4 && DV <=256 ?16 :INT_MAX ; 1169const bool use_gqa_opt = mask && max_bias == 0.0f && Q -> ne [1 ] <=gqa_limit && K -> ne [1 ] %FATTN_KQ_STRIDE == 0 ; 1170 1171if constexpr (DV == 512 ) { 1172if (use_gqa_opt && gqa_ratio %16 == 0 ) { 1173launch_fattn_tile_switch_ncols1 < DKQ ,DV ,16 ,use_logit_softcap > (ctx ,dst ); 1174return ; 1175 } 1176if (use_gqa_opt && gqa_ratio %4 == 0 ) { 1177launch_fattn_tile_switch_ncols1 < DKQ ,DV ,4 ,use_logit_softcap > (ctx ,dst ); 1178return ; 1179 } 1180// ncols2=2 and ncols2=1 fallbacks only for cases where ncols=2 config exists (DKQ == DV). 1181// For DKQ == 576, DV == 512 only GQA-optimized variants are implemented. 1182if constexpr (DKQ == DV ) { 1183if (use_gqa_opt && gqa_ratio %2 == 0 ) { 1184launch_fattn_tile_switch_ncols1 < DKQ ,DV ,2 ,use_logit_softcap > (ctx ,dst ); 1185return ; 1186 } 1187launch_fattn_tile_switch_ncols1 < DKQ ,DV ,1 ,use_logit_softcap > (ctx ,dst ); 1188return ; 1189 } 1190 } 1191 1192if constexpr (DV <=256 ) { 1193if (use_gqa_opt && gqa_ratio %8 == 0 ) { 1194launch_fattn_tile_switch_ncols1 < DKQ ,DV ,8 ,use_logit_softcap > (ctx ,dst ); 1195return ; 1196 } 1197 1198if (use_gqa_opt && gqa_ratio %4 == 0 ) { 1199launch_fattn_tile_switch_ncols1 < DKQ ,DV ,4 ,use_logit_softcap > (ctx ,dst ); 1200return ; 1201 } 1202 1203if (use_gqa_opt && gqa_ratio %2 == 0 ) { 1204launch_fattn_tile_switch_ncols1 < DKQ ,DV ,2 ,use_logit_softcap > (ctx ,dst ); 1205return ; 1206 } 1207 1208launch_fattn_tile_switch_ncols1 < DKQ ,DV ,1 ,use_logit_softcap > (ctx ,dst ); 1209return ; 1210 } 1211GGML_ABORT ("fatal error" ); 1212} 1213 1214template < int DKQ ,int DV > 1215void ggml_sycl_flash_attn_ext_tile_case (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 1216const ggml_tensor * KQV = dst ; 1217 1218float logit_softcap ; 1219memcpy (& logit_softcap , (const float * )KQV -> op_params + 2 ,sizeof (float )); 1220 1221if (logit_softcap == 0.0f ) { 1222constexpr bool use_logit_softcap = false; 1223launch_fattn_tile_switch_ncols2 < DKQ ,DV ,use_logit_softcap > (ctx ,dst ); 1224 }else { 1225constexpr bool use_logit_softcap = true; 1226launch_fattn_tile_switch_ncols2 < DKQ ,DV ,use_logit_softcap > (ctx ,dst ); 1227 } 1228} 1229 1230void ggml_sycl_flash_attn_ext_tile (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ); 1231 1232#define DECL_FATTN_TILE_CASE (DKQ ,DV ) \ 1233 template void ggml_sycl_flash_attn_ext_tile_case \ 1234 <DKQ, DV>(ggml_backend_sycl_context & ctx, ggml_tensor * dst) \ 1235 1236extern DECL_FATTN_TILE_CASE (40 ,40 ); 1237extern DECL_FATTN_TILE_CASE (64 ,64 ); 1238extern DECL_FATTN_TILE_CASE (72 ,72 ); 1239extern DECL_FATTN_TILE_CASE (80 ,80 ); 1240extern DECL_FATTN_TILE_CASE (96 ,96 ); 1241extern DECL_FATTN_TILE_CASE (112 ,112 ); 1242extern DECL_FATTN_TILE_CASE (128 ,128 ); 1243extern DECL_FATTN_TILE_CASE (256 ,256 ); 1244extern DECL_FATTN_TILE_CASE (512 ,512 ); 1245extern DECL_FATTN_TILE_CASE (576 ,512 ); 1246