char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
cc83d7b48
char/aliceai-t5-moe
1#pragma once 2 3#include <sycl/sycl.hpp> 4#include "dpct/helper.hpp" 5#include "common.hpp" 6#include "convert.hpp" 7#include "vecdotq.hpp" 8#include "fattn-buffers.hpp" 9#include "fattn.hpp" 10 11#include "ggml.h" 12 13#include <cstdint> 14#include <cmath> 15#include <float.h> 16 17 18#define FATTN_KQ_STRIDE 256 19#define HALF_MAX_HALF sycl::half(65504.0f/2) // Use neg. of this instead of -INFINITY to initialize KQ max vals to avoid NaN upon subtraction. 20#define SOFTMAX_FTZ_THRESHOLD -20.0f // Softmax exp. of values smaller than this are flushed to zero to avoid NaNs. 21#define FATTN_KQ_MAX_OFFSET (3.0f*0.6931f) 22 23typedef void (* fattn_kernel_t )( 24const char * Q , 25const char * K , 26const char * V , 27const char * mask , 28const char * sinks , 29const int * KV_max , 30float * dst , 31 sycl::float2 * dst_meta , 32const float scale , 33const float max_bias , 34const float m0 , 35const float m1 , 36const uint32_t n_head_log2 , 37const float logit_softcap , 38const int32_t ne00 , 39const sycl::uint3 ne01 , 40const int32_t ne02 , 41const int32_t ne03 , 42const int32_t nb01 , 43const int32_t nb02 , 44const int32_t nb03 , 45const int32_t ne10 , 46const int32_t ne11 , 47const int32_t ne12 , 48const int32_t ne13 , 49const int32_t nb11 , 50const int32_t nb12 , 51const int64_t nb13 , 52const int32_t nb21 , 53const int32_t nb22 , 54const int64_t nb23 , 55const int32_t ne31 , 56const int32_t ne32 , 57const int32_t ne33 , 58const int32_t nb31 , 59const int32_t nb32 , 60const int64_t nb33 ); 61 62typedef float (* vec_dot_KQ_t )( 63const char * __restrict__K_c ,const void * __restrict__Q_v ,const int * __restrict__Q_q8 ,const void * __restrict__Q_ds ); 64 65template < int D ,int nthreads > 66static __dpct_inline__ float vec_dot_fattn_vec_KQ_f16 (const char * __restrict__K_c , 67const void * __restrict__Q_v , 68const int * __restrict__Q_q8 , 69const void * __restrict__Q_ds_v ) { 70const sycl::half2 * K_h2 = (const sycl::half2 * )K_c ; 71GGML_UNUSED (Q_q8 ); 72GGML_UNUSED (Q_ds_v ); 73 74constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes (); 75constexpr int cpy_ne = cpy_nb /4 ; 76 77float sum = 0.0f ; 78 79#pragma unroll 80for (int k_KQ_0 = 0 ;k_KQ_0 < D /2 ;k_KQ_0 += nthreads * cpy_ne ) { 81 sycl::half2 tmp [cpy_ne ]; 82ggml_sycl_memcpy_1 < sizeof (tmp )> ( 83tmp , 84K_h2 + k_KQ_0 + (sycl::ext::oneapi::this_work_item::get_nd_item < 3 > ().get_local_id (2 ) %nthreads )* cpy_ne ); 85#pragma unroll 86for (int k_KQ_1 = 0 ;k_KQ_1 < cpy_ne ;++ k_KQ_1 ) { 87#ifdef GGML_SYCL_F16 88ggml_sycl_mad (sum ,tmp [k_KQ_1 ] , ((const sycl::half2 * )Q_v )[k_KQ_0 /nthreads + k_KQ_1 ]); 89#else 90ggml_sycl_mad (sum ,__half22float2 (tmp [k_KQ_1 ]), ((const sycl::float2 * )Q_v )[k_KQ_0 /nthreads + k_KQ_1 ]); 91#endif // GGML_SYCL_F16 92 } 93 } 94 95return sum ; 96} 97 98template < int D ,int nthreads ,int warp_size > 99static __dpct_inline__ float vec_dot_fattn_vec_KQ_q4_0 (const char * __restrict__K_c , 100const void * __restrict__Q_v , 101const int * __restrict__Q_q8 , 102const void * __restrict__Q_ds_v ) { 103auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 104 105const block_q4_0 * K_q4_0 = (const block_q4_0 * )K_c ; 106GGML_UNUSED (Q_v ); 107 108float sum = 0.0f ; 109 110#pragma unroll 111for (int k_KQ_0 = 0 ;k_KQ_0 < int (D /sizeof (int ));k_KQ_0 += nthreads ) { 112const int k_KQ = 113k_KQ_0 + (nthreads == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads ); 114 115const int ib = k_KQ /QI8_1 ; 116const int iqs4 = k_KQ %QI4_0 ; 117const int shift = k_KQ & (QI8_1 /2 ); 118 119int v ; 120ggml_sycl_memcpy_1 < sizeof (int ),2 > (& v ,K_q4_0 [ib ].qs + sizeof (int )* iqs4 ); 121v = (v >>shift )& 0x0F0F0F0F ; 122const int u = Q_q8 [k_KQ_0 /nthreads ]; 123 124const int sumi = ggml_sycl_dp4a (v ,u ,0 ); 125 126const sycl::float2 Q_ds = ((const sycl::float2 * )Q_ds_v )[k_KQ_0 /nthreads ]; 127sum += __half2float (K_q4_0 [ib ].d )* (sumi * Q_ds .x ()- (8 /QI8_1 )* Q_ds .y ()); 128 } 129 130return sum ; 131} 132 133template < int D ,int nthreads ,int warp_size > 134static __dpct_inline__ float vec_dot_fattn_vec_KQ_q4_1 (const char * __restrict__K_c , 135const void * __restrict__Q_v , 136const int * __restrict__Q_q8 , 137const void * __restrict__Q_ds_v ) { 138auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 139const block_q4_1 * K_q4_1 = (const block_q4_1 * )K_c ; 140GGML_UNUSED (Q_v ); 141 142float sum = 0.0f ; 143 144#pragma unroll 145for (int k_KQ_0 = 0 ;k_KQ_0 < int (D /sizeof (int ));k_KQ_0 += nthreads ) { 146const int k_KQ = 147k_KQ_0 + (nthreads == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads ); 148 149const int ib = k_KQ /QI8_1 ; 150const int iqs4 = k_KQ %QI4_1 ; 151const int shift = k_KQ & (QI8_1 /2 ); 152 153int v ; 154ggml_sycl_memcpy_1 < sizeof (int )> (& v ,K_q4_1 [ib ].qs + sizeof (int )* iqs4 ); 155v = (v >>shift )& 0x0F0F0F0F ; 156const int u = Q_q8 [k_KQ_0 /nthreads ]; 157 158const int sumi = ggml_sycl_dp4a (v ,u ,0 ); 159 160const sycl::float2 K_dm = (K_q4_1 [ib ].dm ).template convert < float , sycl::rounding_mode::automatic > (); 161const sycl::float2 Q_ds = ((const sycl::float2 * )Q_ds_v )[k_KQ_0 /nthreads ]; 162 163sum += K_dm .x ()* Q_ds .x ()* sumi + K_dm .y ()* Q_ds .y ()/QI8_1 ; 164 } 165 166return sum ; 167} 168 169template < int D ,int nthreads ,int warp_size > 170static __dpct_inline__ float vec_dot_fattn_vec_KQ_q5_0 (const char * __restrict__K_c , 171const void * __restrict__Q_v , 172const int * __restrict__Q_q8 , 173const void * __restrict__Q_ds_v ) { 174auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 175const block_q5_0 * K_q5_0 = (const block_q5_0 * )K_c ; 176GGML_UNUSED (Q_v ); 177 178float sum = 0.0f ; 179 180#pragma unroll 181for (int k_KQ_0 = 0 ;k_KQ_0 < int (D /sizeof (int ));k_KQ_0 += nthreads ) { 182const int k_KQ = 183k_KQ_0 + (nthreads == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads ); 184 185const int ib = k_KQ /QI8_1 ; 186const int iqs4 = k_KQ %QI5_0 ; 187const int iqs8 = k_KQ %QI8_1 ; 188const int shift = k_KQ & (QI8_1 /2 ); 189 190int v ; 191ggml_sycl_memcpy_1 < sizeof (int ),2 > (& v ,K_q5_0 [ib ].qs + sizeof (int )* iqs4 ); 192v = (v >>shift )& 0x0F0F0F0F ; 193 194 { 195int vh ; 196ggml_sycl_memcpy_1 < sizeof (int ),2 > (& vh ,K_q5_0 [ib ].qh ); 197vh >>=iqs8 * QI5_0 ; 198 199v |= (vh <<4 )& 0x00000010 ;// 0 -> 4 200v |= (vh <<11 )& 0x00001000 ;// 1 -> 12 201v |= (vh <<18 )& 0x00100000 ;// 2 -> 20 202v |= (vh <<25 )& 0x10000000 ;// 3 -> 28 203 } 204 205const int u = Q_q8 [k_KQ_0 /nthreads ]; 206 207const int sumi = ggml_sycl_dp4a (v ,u ,0 ); 208 209const sycl::float2 Q_ds = ((const sycl::float2 * )Q_ds_v )[k_KQ_0 /nthreads ]; 210 211sum += __half2float (K_q5_0 [ib ].d )* (sumi * Q_ds .x ()- (16 /QI8_1 )* Q_ds .y ()); 212 } 213 214return sum ; 215} 216 217template < int D ,int nthreads ,int warp_size > 218static __dpct_inline__ float vec_dot_fattn_vec_KQ_q5_1 (const char * __restrict__K_c , 219const void * __restrict__Q_v , 220const int * __restrict__Q_q8 , 221const void * __restrict__Q_ds_v ) { 222auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 223const block_q5_1 * K_q5_1 = (const block_q5_1 * )K_c ; 224GGML_UNUSED (Q_v ); 225 226float sum = 0.0f ; 227 228#pragma unroll 229for (int k_KQ_0 = 0 ;k_KQ_0 < int (D /sizeof (int ));k_KQ_0 += nthreads ) { 230const int k_KQ = 231k_KQ_0 + (nthreads == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads ); 232 233const int ib = k_KQ /QI8_1 ; 234const int iqs4 = k_KQ %QI5_1 ; 235const int iqs8 = k_KQ %QI8_1 ; 236const int shift = k_KQ & (QI8_1 /2 ); 237 238int v ; 239ggml_sycl_memcpy_1 < sizeof (int )> (& v ,K_q5_1 [ib ].qs + sizeof (int )* iqs4 ); 240v = (v >>shift )& 0x0F0F0F0F ; 241 242 { 243int vh ; 244ggml_sycl_memcpy_1 < sizeof (int )> (& vh ,K_q5_1 [ib ].qh ); 245vh >>=iqs8 * QI5_0 ; 246 247v |= (vh <<4 )& 0x00000010 ;// 0 -> 4 248v |= (vh <<11 )& 0x00001000 ;// 1 -> 12 249v |= (vh <<18 )& 0x00100000 ;// 2 -> 20 250v |= (vh <<25 )& 0x10000000 ;// 3 -> 28 251 } 252 253const int u = Q_q8 [k_KQ_0 /nthreads ]; 254 255const int sumi = ggml_sycl_dp4a (v ,u ,0 ); 256 257const sycl::float2 K_dm = (K_q5_1 [ib ].dm ).template convert < float , sycl::rounding_mode::automatic > (); 258const sycl::float2 Q_ds = ((const sycl::float2 * )Q_ds_v )[k_KQ_0 /nthreads ]; 259 260sum += K_dm .x ()* Q_ds .x ()* sumi + K_dm .y ()* Q_ds .y ()/QI8_1 ; 261 } 262 263return sum ; 264} 265 266template < int D ,int nthreads ,int warp_size > 267static __dpct_inline__ float vec_dot_fattn_vec_KQ_q8_0 (const char * __restrict__K_c , 268const void * __restrict__Q_v , 269const int * __restrict__Q_q8 , 270const void * __restrict__Q_ds_v ) { 271auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 272const block_q8_0 * K_q8_0 = (const block_q8_0 * )K_c ; 273GGML_UNUSED (Q_v ); 274 275float sum = 0.0f ; 276 277#pragma unroll 278for (int k_KQ_0 = 0 ;k_KQ_0 < int (D /sizeof (int ));k_KQ_0 += nthreads ) { 279const int k_KQ = 280k_KQ_0 + (nthreads == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads ); 281 282const int ib = k_KQ /QI8_0 ; 283const int iqs = k_KQ %QI8_0 ; 284 285int v ; 286ggml_sycl_memcpy_1 < sizeof (v ),2 > (& v ,K_q8_0 [ib ].qs + 4 * iqs ); 287 288const sycl::float2 * Q_ds = (const sycl::float2 * )Q_ds_v ; 289const float Q_d = Q_ds [k_KQ_0 /nthreads ].x (); 290 291sum += vec_dot_q8_0_q8_1_impl < float ,1 > (& v ,& Q_q8 [k_KQ_0 /nthreads ],K_q8_0 [ib ].d ,Q_d ); 292 } 293 294return sum ; 295} 296 297template < typename Tds ,int ni ,int warp_size > 298static __dpct_inline__ void quantize_q8_1_to_shared (const float * __restrict__x , 299const float scale , 300int * __restrict__yq32 , 301void * __restrict__yds ) { 302auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 303 304float vals [sizeof (int )]= {0.0f }; 305#pragma unroll 306for (int l = 0 ;l < int (sizeof (int ));++ l ) { 307vals [l ]= 308 (ni == warp_size || item_ct1 .get_local_id (2 )< ni ) ?scale * x [4 * item_ct1 .get_local_id (2 )+ l ] :0.0f ; 309 } 310 311float amax = sycl::fabs (vals [0 ]); 312float sum = vals [0 ]; 313#pragma unroll 314for (int l = 1 ;l < int (sizeof (int ));++ l ) { 315amax = sycl::fmax (amax , sycl::fabs (vals [l ])); 316sum += vals [l ]; 317 } 318#pragma unroll 319for (int mask = QI8_1 /2 ;mask > 0 ;mask >>=1 ) { 320amax = sycl::fmax ( 321amax , dpct::permute_sub_group_by_xor (sycl::ext::oneapi::this_work_item::get_sub_group (),amax ,mask )); 322sum += dpct::permute_sub_group_by_xor (sycl::ext::oneapi::this_work_item::get_sub_group (),sum ,mask ); 323 } 324 325const float d = amax /127 ; 326int q32 = 0 ; 327int8_t * q8 = (int8_t * )& q32 ; 328 329if (d != 0.0f ) { 330#pragma unroll 331for (int l = 0 ;l < int (sizeof (int ));++ l ) { 332q8 [l ]= sycl::round (vals [l ] /d ); 333 } 334 } 335 336yq32 [item_ct1 .get_local_id (2 )]= q32 ; 337if (item_ct1 .get_local_id (2 ) %QI8_1 == 0 && (ni == warp_size || item_ct1 .get_local_id (2 )< ni )) { 338if (std::is_same < Tds , sycl::half2 > ::value ) { 339 ((sycl::half2 * )yds )[item_ct1 .get_local_id (2 )/QI8_1 ]= make_half2 (d ,sum ); 340 }else { 341 ((sycl::float2 * )yds )[item_ct1 .get_local_id (2 )/QI8_1 ]= make_float2 (d ,sum ); 342 } 343 } 344} 345 346typedef void (* dequantize_V_t )(const void * ,void * ,const int64_t ); 347 348template < typename T ,int ne > 349static __dpct_inline__ void dequantize_V_f16 (const void * __restrict__vx ,void * __restrict__dst ,const int64_t i0 ) { 350if constexpr (std::is_same_v < T , sycl::half > ) { 351ggml_sycl_memcpy_1 < ne * sizeof (sycl::half )> (dst , (const sycl::half * )vx + i0 ); 352 }else if constexpr (std::is_same_v < T ,float > ) { 353 static_assert(ne %2 == 0 ,"bad ne" ); 354 sycl::half2 tmp [ne /2 ]; 355ggml_sycl_memcpy_1 < ne * sizeof (sycl::half )> (tmp , (const sycl::half * )vx + i0 ); 356 sycl::float2 * dst_f2 = (sycl::float2 * )dst ; 357#pragma unroll 358for (int l = 0 ;l < ne /2 ;++ l ) { 359dst_f2 [l ]= tmp [l ].template convert < float , sycl::rounding_mode::automatic > (); 360 } 361 }else { 362 static_assert(std::is_same_v < T ,void > ,"unsupported type" ); 363 } 364} 365 366template < typename T ,int ne > 367static __dpct_inline__ void dequantize_V_q4_0 (const void * __restrict__vx ,void * __restrict__dst ,const int64_t i0 ) { 368const block_q4_0 * x = (const block_q4_0 * )vx ; 369 370const int64_t ib = i0 /QK4_0 ; 371const int iqs = i0 % (QK4_0 /2 ); 372const int shift = (i0 %QK4_0 ) / (QK4_0 /2 ); 373 374int q ; 375 static_assert(ne == 2 || ne == 4 ,"bad ne" ); 376ggml_sycl_memcpy_1 < ne ,2 > (& q ,x [ib ].qs + iqs ); 377q >>=4 * shift ; 378q &=0x0F0F0F0F ; 379q = dpct::vectorized_binary < sycl::char4 > (q ,0x08080808 , dpct::sub_sat ()); 380 381const int8_t * q8 = (const int8_t * )& q ; 382 383#ifdef GGML_SYCL_F16 384if constexpr (std::is_same_v < T , sycl::half > ) { 385const sycl::half2 d = sycl::half2 (x [ib ].d ); 386 387#pragma unroll 388for (int l0 = 0 ;l0 < ne ;l0 += 2 ) { 389 ((sycl::half2 * )dst )[l0 /2 ]= d * sycl::half2 (q8 [l0 + 0 ],q8 [l0 + 1 ]); 390 } 391 }else 392#endif // GGML_SYCL_F16 393if constexpr (std::is_same_v < T ,float > ) { 394const float d = x [ib ].d ; 395 396#pragma unroll 397for (int l = 0 ;l < ne ;++ l ) { 398 ((float * )dst )[l ]= d * q8 [l ]; 399 } 400 }else { 401 static_assert(std::is_same_v < T ,void > ,"bad type" ); 402 } 403} 404 405template < typename T ,int ne > 406static __dpct_inline__ void dequantize_V_q4_1 (const void * __restrict__vx ,void * __restrict__dst ,const int64_t i0 ) { 407const block_q4_1 * x = (const block_q4_1 * )vx ; 408 409const int64_t ib = i0 /QK4_1 ; 410const int iqs = i0 % (QK4_1 /2 ); 411const int shift = (i0 %QK4_1 ) / (QK4_1 /2 ); 412 413int q ; 414 static_assert(ne == 2 || ne == 4 ,"bad ne" ); 415ggml_sycl_memcpy_1 < ne > (& q ,x [ib ].qs + iqs ); 416q >>=4 * shift ; 417q &=0x0F0F0F0F ; 418 419const int8_t * q8 = (const int8_t * )& q ; 420 421#ifdef GGML_SYCL_F16 422if constexpr (std::is_same_v < T , sycl::half > ) { 423const sycl::half2 dm = x [ib ].dm ; 424const sycl::half2 d = sycl::half2 (dm [0 ]); 425const sycl::half2 m = sycl::half2 (dm [1 ]); 426 427#pragma unroll 428for (int l0 = 0 ;l0 < ne ;l0 += 2 ) { 429 ((sycl::half2 * )dst )[l0 /2 ]= d * sycl::half2 (q8 [l0 + 0 ],q8 [l0 + 1 ])+ m ; 430 } 431 }else 432#endif // GGML_SYCL_F16 433if constexpr (std::is_same_v < T ,float > ) { 434const sycl::float2 dm = (x [ib ].dm ).template convert < float , sycl::rounding_mode::automatic > (); 435 436#pragma unroll 437for (int l = 0 ;l < ne ;++ l ) { 438 ((float * )dst )[l ]= dm .x ()* q8 [l ]+ dm .y (); 439 } 440 }else { 441 static_assert(std::is_same_v < T ,void > ,"bad type" ); 442 } 443} 444 445template < typename T ,int ne > 446static __dpct_inline__ void dequantize_V_q5_0 (const void * __restrict__vx ,void * __restrict__dst ,const int64_t i0 ) { 447const block_q5_0 * x = (const block_q5_0 * )vx ; 448 449const int64_t ib = i0 /QK5_0 ; 450const int idq = i0 %QK5_0 ; 451const int iqs = i0 % (QK5_0 /2 ); 452const int shift = (i0 %QK5_0 ) / (QK5_0 /2 ); 453 454int q ; 455 static_assert(ne == 2 || ne == 4 ,"bad ne" ); 456ggml_sycl_memcpy_1 < ne ,2 > (& q ,x [ib ].qs + iqs ); 457q >>=4 * shift ; 458q &=0x0F0F0F0F ; 459 460 { 461int qh ; 462ggml_sycl_memcpy_1 < ne ,2 > (& qh ,x [ib ].qh ); 463#pragma unroll 464for (int l = 0 ;l < ne ;++ l ) { 465q |= ((qh >> (idq + l ))& 0x00000001 ) << (8 * l + 4 ); 466 } 467 } 468 469q = dpct::vectorized_binary < sycl::char4 > (q ,0x10101010 , dpct::sub_sat ()); 470 471const int8_t * q8 = (const int8_t * )& q ; 472 473#ifdef GGML_SYCL_F16 474if constexpr (std::is_same_v < T , sycl::half > ) { 475const sycl::half2 d = sycl::half2 (x [ib ].d ); 476 477#pragma unroll 478for (int l0 = 0 ;l0 < ne ;l0 += 2 ) { 479 ((sycl::half2 * )dst )[l0 /2 ]= d * sycl::half2 (q8 [l0 + 0 ],q8 [l0 + 1 ]); 480 } 481 }else 482#endif // GGML_SYCL_F16 483if constexpr (std::is_same_v < T ,float > ) { 484const float d = x [ib ].d ; 485 486#pragma unroll 487for (int l = 0 ;l < ne ;++ l ) { 488 ((float * )dst )[l ]= d * q8 [l ]; 489 } 490 }else { 491 static_assert(std::is_same_v < T ,void > ,"bad type" ); 492 } 493} 494 495template < typename T ,int ne > 496static __dpct_inline__ void dequantize_V_q5_1 (const void * __restrict__vx ,void * __restrict__dst ,const int64_t i0 ) { 497const block_q5_1 * x = (const block_q5_1 * )vx ; 498 499const int64_t ib = i0 /QK5_1 ; 500const int idq = i0 %QK5_1 ; 501const int iqs = i0 % (QK5_1 /2 ); 502const int shift = (i0 %QK5_1 ) / (QK5_1 /2 ); 503 504int q ; 505 static_assert(ne == 2 || ne == 4 ,"bad ne" ); 506ggml_sycl_memcpy_1 < ne > (& q ,x [ib ].qs + iqs ); 507q >>=4 * shift ; 508q &=0x0F0F0F0F ; 509 510 { 511int qh ; 512ggml_sycl_memcpy_1 < ne > (& qh ,x [ib ].qh ); 513#pragma unroll 514for (int l = 0 ;l < ne ;++ l ) { 515q |= ((qh >> (idq + l ))& 0x00000001 ) << (8 * l + 4 ); 516 } 517 } 518 519const int8_t * q8 = (const int8_t * )& q ; 520 521#ifdef GGML_SYCL_F16 522if constexpr (std::is_same_v < T , sycl::half > ) { 523const sycl::half2 dm = x [ib ].dm ; 524const sycl::half2 d = sycl::half2 (dm [0 ]); 525const sycl::half2 m = sycl::half2 (dm [1 ]); 526 527#pragma unroll 528for (int l0 = 0 ;l0 < ne ;l0 += 2 ) { 529 ((sycl::half2 * )dst )[l0 /2 ]= d * sycl::half2 (q8 [l0 + 0 ],q8 [l0 + 1 ])+ m ; 530 } 531 }else 532#endif // GGML_SYCL_F16 533if constexpr (std::is_same_v < T ,float > ) { 534const sycl::float2 dm = (x [ib ].dm ).template convert < float , sycl::rounding_mode::automatic > (); 535 536#pragma unroll 537for (int l = 0 ;l < ne ;++ l ) { 538 ((float * )dst )[l ]= dm .x ()* q8 [l ]+ dm .y (); 539 } 540 }else { 541 static_assert(std::is_same_v < T ,void > ,"bad type" ); 542 } 543} 544 545template < typename T ,int ne > 546static __dpct_inline__ void dequantize_V_q8_0 (const void * __restrict__vx ,void * __restrict__dst ,const int64_t i0 ) { 547const block_q8_0 * x = (const block_q8_0 * )vx ; 548 549const int64_t ib = i0 /QK8_0 ; 550const int iqs = i0 %QK8_0 ; 551 552 static_assert(ne %2 == 0 ,"bad ne" ); 553int8_t qs [ne ]; 554ggml_sycl_memcpy_1 < ne ,2 > (qs ,x [ib ].qs + iqs ); 555 556#ifdef GGML_SYCL_F16 557if constexpr (std::is_same < T , sycl::half > ::value ) { 558const sycl::half2 d = sycl::half2 (x [ib ].d ); 559 560#pragma unroll 561for (int l0 = 0 ;l0 < ne ;l0 += 2 ) { 562 ((sycl::half2 * )dst )[l0 /2 ]= d * make_half2 (qs [l0 + 0 ],qs [l0 + 1 ]); 563 } 564 }else 565#endif // GGML_SYCL_F16 566if constexpr (std::is_same < T ,float > ::value ) { 567const float d = x [ib ].d ; 568 569#pragma unroll 570for (int l = 0 ;l < ne ;++ l ) { 571 ((float * )dst )[l ]= d * qs [l ]; 572 } 573 }else { 574 static_assert(std::is_same_v < T ,void > ,"unsupported type" ); 575 } 576} 577 578template < int type_K ,int D ,int nthreads ,int warp_size > 579constexpr vec_dot_KQ_t get_vec_dot_KQ () { 580if constexpr (type_K == GGML_TYPE_F16 ) { 581return vec_dot_fattn_vec_KQ_f16 < D ,nthreads > ; 582 }else if constexpr (type_K == GGML_TYPE_Q4_0 ) { 583return vec_dot_fattn_vec_KQ_q4_0 < D ,nthreads ,warp_size > ; 584 }else if constexpr (type_K == GGML_TYPE_Q4_1 ) { 585return vec_dot_fattn_vec_KQ_q4_1 < D ,nthreads ,warp_size > ; 586 }else if constexpr (type_K == GGML_TYPE_Q5_0 ) { 587return vec_dot_fattn_vec_KQ_q5_0 < D ,nthreads ,warp_size > ; 588 }else if constexpr (type_K == GGML_TYPE_Q5_1 ) { 589return vec_dot_fattn_vec_KQ_q5_1 < D ,nthreads ,warp_size > ; 590 }else if constexpr (type_K == GGML_TYPE_Q8_0 ) { 591return vec_dot_fattn_vec_KQ_q8_0 < D ,nthreads ,warp_size > ; 592 }else { 593 static_assert(type_K == -1 ,"bad type" ); 594return nullptr ; 595 } 596} 597 598template < int type_V ,typename T ,int ne > 599constexpr dequantize_V_t get_dequantize_V () { 600if constexpr (type_V == GGML_TYPE_F16 ) { 601return dequantize_V_f16 < T ,ne > ; 602 }else if constexpr (type_V == GGML_TYPE_Q4_0 ) { 603return dequantize_V_q4_0 < T ,ne > ; 604 }else if constexpr (type_V == GGML_TYPE_Q4_1 ) { 605return dequantize_V_q4_1 < T ,ne > ; 606 }else if constexpr (type_V == GGML_TYPE_Q5_0 ) { 607return dequantize_V_q5_0 < T ,ne > ; 608 }else if constexpr (type_V == GGML_TYPE_Q5_1 ) { 609return dequantize_V_q5_1 < T ,ne > ; 610 }else if constexpr (type_V == GGML_TYPE_Q8_0 ) { 611return dequantize_V_q8_0 < T ,ne > ; 612 }else { 613 static_assert(type_V == -1 ,"bad type" ); 614return nullptr ; 615 } 616} 617 618template < int ncols1 ,int warp_size > 619static void flash_attn_mask_to_KV_max (const sycl::half2 * __restrict__mask , 620int * __restrict__KV_max , 621const int ne30 , 622const int s31 , 623const int s33 , 624int * buf_iw ) { 625auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 626const int ne31 = item_ct1 .get_group_range (2 ); 627const int tid = item_ct1 .get_local_id (2 ); 628const int sequence = item_ct1 .get_group (1 ); 629const int jt = item_ct1 .get_group (2 ); 630 631mask += sequence * s33 + jt * ncols1 * s31 ; 632 633if (tid < warp_size ) { 634buf_iw [tid ]= 1 ; 635 } 636item_ct1 .barrier (sycl::access::fence_space::local_space ); 637 638int KV_max_sj = (ne30 - 1 )* FATTN_KQ_STRIDE ; 639for (;KV_max_sj >=0 ;KV_max_sj -= FATTN_KQ_STRIDE ) { 640int all_inf = 1 ; 641 642#pragma unroll 643for (int j = 0 ;j < ncols1 ;++ j ) { 644const sycl::float2 tmp = 645mask [j * s31 + KV_max_sj /2 + tid ].template convert < float , sycl::rounding_mode::automatic > (); 646all_inf = all_inf && int (sycl::isinf ((float ) (tmp .x ())))&& int (sycl::isinf ((float ) (tmp .y ()))); 647 } 648 649all_inf = warp_reduce_all < warp_size > (all_inf ); 650if (tid %warp_size == 0 ) { 651buf_iw [tid /warp_size ]= all_inf ; 652 } 653item_ct1 .barrier (sycl::access::fence_space::local_space ); 654all_inf = buf_iw [tid %warp_size ]; 655item_ct1 .barrier (sycl::access::fence_space::local_space ); 656all_inf = warp_reduce_all < warp_size > (all_inf ); 657 658if (!all_inf ) { 659break ; 660 } 661 } 662 663// If the break in the loop was not triggered, KV_max_sj is now -FATTN_KQ_STRIDE. 664// If the break was triggered it's the lower edge of the tile with the first non-masked values. 665// In either case, walk back the decrementation by FATTN_KQ_STRIDE. 666KV_max_sj += FATTN_KQ_STRIDE ; 667 668if (item_ct1 .get_local_id (2 )!= 0 ) { 669return ; 670 } 671 672KV_max [sequence * ne31 + jt ]= KV_max_sj ; 673} 674 675template < int D ,int ncols1 ,int ncols2 > // D == head size 676 677static void flash_attn_stream_k_fixup (float * __restrict__dst , 678const sycl::float2 * __restrict__dst_fixup , 679const int ne01 , 680const int ne02 , 681const int ne03 , 682const int ne11 , 683const int ne12 , 684const int nbatch_fa ) { 685auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 686constexpr int ncols = ncols1 * ncols2 ; 687 688const int bidx0 = item_ct1 .get_group (2 ); 689const int j = item_ct1 .get_group (1 ); 690const int c = item_ct1 .get_group (0 ); 691const int jc = j * ncols2 + c ; 692const int tid = item_ct1 .get_local_id (2 ); 693 694const float * dst_fixup_data = ((const float * )dst_fixup )+ item_ct1 .get_group_range (2 )* (2 * 2 * ncols ); 695 696const int gqa_ratio = ne02 /ne12 ;// With grouped query attention there are > 1 Q matrices per K, V matrix. 697 698const int iter_k = (ne11 + (nbatch_fa - 1 )) /nbatch_fa ; 699const int iter_j = (ne01 + (ncols1 - 1 )) /ncols1 ; 700const int iter_z_gqa = (gqa_ratio + (ncols2 - 1 )) /ncols2 ; 701 702const int kbc0 = int64_t (bidx0 + 0 )* (iter_k * iter_j * iter_z_gqa * ne12 * ne03 ) /item_ct1 .get_group_range (2 ); 703const int kbc0_stop = 704int64_t (bidx0 + 1 )* (iter_k * iter_j * iter_z_gqa * ne12 * ne03 ) /item_ct1 .get_group_range (2 ); 705 706const bool did_not_have_any_data = kbc0 == kbc0_stop ; 707const bool wrote_beginning_of_tile = kbc0 %iter_k == 0 ; 708const bool did_not_write_last = kbc0 /iter_k == kbc0_stop /iter_k && kbc0_stop %iter_k != 0 ; 709if (did_not_have_any_data || wrote_beginning_of_tile || did_not_write_last ) { 710return ; 711 } 712 713// z_KV == K/V head index, zt_gqa = Q head start index per K/V head, jt = token position start index 714const int sequence = kbc0 /(iter_k * iter_j * iter_z_gqa * ne12 ); 715const int z_KV = (kbc0 - iter_k * iter_j * iter_z_gqa * ne12 * sequence )/(iter_k * iter_j * iter_z_gqa ); 716const int zt_gqa = (kbc0 - iter_k * iter_j * iter_z_gqa * ne12 * sequence - iter_k * iter_j * iter_z_gqa * z_KV )/(iter_k * iter_j ); 717const int jt = (kbc0 - iter_k * iter_j * iter_z_gqa * ne12 * sequence - iter_k * iter_j * iter_z_gqa * z_KV - iter_k * iter_j * zt_gqa ) /iter_k ; 718 719const int zt_Q = z_KV * gqa_ratio + zt_gqa * ncols2 ;// Global Q head start index. 720 721if (jt * ncols1 + j >=ne01 || zt_gqa * ncols2 + c >=gqa_ratio ) { 722return ; 723 } 724 725dst += sequence * ne02 * ne01 * D + jt * ne02 * (ncols1 * D )+ zt_Q * D + (j * ne02 + c )* D + tid ; 726 727// Load the partial result that needs a fixup: 728float dst_val = 0.0f ; 729float max_val = 0.0f ; 730float rowsum = 0.0f ; 731 { 732dst_val = * dst ; 733 734const sycl::float2 tmp = dst_fixup [bidx0 * ncols + jc ]; 735max_val = tmp .x (); 736rowsum = tmp .y (); 737 } 738 739// Iterate over previous blocks and compute the combined results. 740// All SYCL blocks that get here must have a previous block that needs a fixup. 741int bidx = bidx0 - 1 ; 742int kbc_stop = kbc0 ; 743while (true) { 744const int kbc = int64_t (bidx )* (iter_k * iter_j * iter_z_gqa * ne12 * ne03 ) /item_ct1 .get_group_range (2 ); 745if (kbc == kbc_stop ) {// Did not have any data. 746bidx -- ; 747kbc_stop = kbc ; 748continue ; 749 } 750 751const float dst_add = dst_fixup_data [bidx * ncols * D + jc * D + tid ]; 752 753const sycl::float2 tmp = dst_fixup [(item_ct1 .get_group_range (2 )+ bidx )* ncols + jc ]; 754 755// Scale the current and new value accumulators depending on the max. values. 756const float max_val_new = sycl::fmax (max_val ,tmp .x ()); 757 758const float diff_val = max_val - max_val_new ; 759const float diff_add = tmp .x ()- max_val_new ; 760 761const float scale_val = diff_val >=SOFTMAX_FTZ_THRESHOLD ? sycl::native::exp (diff_val ) :0.0f ; 762const float scale_add = diff_add >=SOFTMAX_FTZ_THRESHOLD ? sycl::native::exp (diff_add ) :0.0f ; 763 764dst_val = scale_val * dst_val + scale_add * dst_add ; 765rowsum = scale_val * rowsum + scale_add * tmp .y (); 766 767max_val = max_val_new ; 768 769// If this block started in a previous tile we are done and don't need to combine additional partial results. 770if (kbc %iter_k == 0 || kbc /iter_k < kbc0 /iter_k ) { 771break ; 772 } 773bidx -- ; 774kbc_stop = kbc ; 775 } 776 777// Write back final result: 778* dst = dst_val /rowsum ; 779} 780 781template < int D > // D == head size 782 783static void flash_attn_combine_results (const float * __restrict__VKQ_parts , 784const sycl::float2 * __restrict__VKQ_meta , 785float * __restrict__dst , 786const int parallel_blocks , 787uint8_t * dpct_local ) { 788// Dimension 0: threadIdx.x 789// Dimension 1: blockIdx.x 790// Dimension 2: blockIdx.y 791// Dimension 3: blockIdx.z 792// Memory layout is permuted with [0, 2, 1, 3] 793 794auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 795const int ne01 = item_ct1 .get_group_range (2 ); 796const int ne02 = item_ct1 .get_group_range (1 ); 797 798const int col = item_ct1 .get_group (2 ); 799const int head = item_ct1 .get_group (1 ); 800const int sequence = item_ct1 .get_group (0 ); 801 802const int j_dst_unrolled = (sequence * ne01 + col )* ne02 + head ; 803 804VKQ_parts += j_dst_unrolled * parallel_blocks * D ; 805VKQ_meta += j_dst_unrolled * parallel_blocks ; 806dst += j_dst_unrolled * D ; 807 808const int tid = item_ct1 .get_local_id (2 ); 809__builtin_assume (tid < D ); 810 811auto meta = (sycl::float2 * )dpct_local ; 812for (int i = tid ;i < 2 * parallel_blocks ;i += D ) { 813 ((float * )meta )[i ]= ((const float * )VKQ_meta ) [i ]; 814 } 815 816item_ct1 .barrier (sycl::access::fence_space::local_space ); 817 818float kqmax = meta [0 ].x (); 819for (int l = 1 ;l < parallel_blocks ;++ l ) { 820kqmax = sycl::max (kqmax ,meta [l ].x ()); 821 } 822 823float VKQ_numerator = 0.0f ; 824float VKQ_denominator = 0.0f ; 825for (int l = 0 ;l < parallel_blocks ;++ l ) { 826const float KQ_max_scale = sycl::native::exp (meta [l ].x ()- kqmax ); 827 828VKQ_numerator += KQ_max_scale * VKQ_parts [l * D + tid ]; 829VKQ_denominator += KQ_max_scale * meta [l ].y (); 830 } 831 832dst [tid ]= VKQ_numerator /VKQ_denominator ; 833} 834 835template < fattn_kernel_t fattn_kernel ,int warp_size > 836static void lauch_kernel ( 837 dpct::dim3 group_range , 838 dpct::dim3 local_range , 839queue_ptr q , 840unsigned int local_mem_size , 841const char * __restrict__Q , 842const char * __restrict__K , 843const char * __restrict__V , 844const char * __restrict__mask , 845const char * __restrict__sinks , 846const int * __restrict__KV_max , 847float * __restrict__dst , 848 sycl::float2 * __restrict__dst_meta , 849const float scale , 850const float max_bias , 851const float m0 , 852const float m1 , 853const uint32_t n_head_log2 , 854const float logit_softcap , 855const int32_t ne00 , 856const sycl::uint3 ne01 , 857const int32_t ne02 , 858const int32_t ne03 , 859const int32_t nb01 , 860const int32_t nb02 , 861const int32_t nb03 , 862const int32_t ne10 , 863const int32_t ne11 , 864const int32_t ne12 , 865const int32_t ne13 , 866const int32_t nb11 , 867const int32_t nb12 , 868const int64_t nb13 , 869const int32_t nb21 , 870const int32_t nb22 , 871const int64_t nb23 , 872const int32_t ne31 , 873const int32_t ne32 , 874const int32_t ne33 , 875const int32_t nb31 , 876const int32_t nb32 , 877const int64_t nb33 ) { 878GGML_UNUSED (local_mem_size ); 879q -> submit ([& ](sycl::handler & cgh ) { 880cgh .parallel_for ( 881 sycl::nd_range < 3 > ( 882static_cast < sycl::range < 3 >> (group_range * local_range ), 883static_cast < sycl::range < 3 >> (local_range )), 884 [= ](sycl::nd_item < 3 > item_ct1 ) [[sycl ::reqd_sub_group_size (warp_size )]] { 885GGML_UNUSED (item_ct1 ); 886fattn_kernel (Q ,K ,V ,mask ,sinks ,KV_max ,dst ,dst_meta ,scale , 887max_bias ,m0 ,m1 ,n_head_log2 ,logit_softcap ,ne00 , 888ne01 ,ne02 ,ne03 ,nb01 ,nb02 ,nb03 ,ne10 ,ne11 , 889ne12 ,ne13 ,nb11 ,nb12 ,nb13 ,nb21 ,nb22 ,nb23 , 890ne31 ,ne32 ,ne33 ,nb31 ,nb32 ,nb33 ); 891 }); 892 }); 893} 894 895template < int DV ,int ncols1 ,int ncols2 ,fattn_kernel_t fattn_kernel ,int warp_size > 896void launch_fattn ( 897ggml_backend_sycl_context & ctx ,ggml_tensor * dst ,const int nwarps ,const size_t nbytes_shared , 898const int nbatch_fa ,const bool need_f16_K ,const bool need_f16_V ,const bool stream_k ) { 899 900constexpr int ncols = ncols1 * ncols2 ; 901 902const ggml_tensor * Q = dst -> src [0 ]; 903const ggml_tensor * K = dst -> src [1 ]; 904const ggml_tensor * V = dst -> src [2 ]; 905 906const bool V_is_K_view = V -> view_src && (V -> view_src == K || (V -> view_src == K -> view_src && V -> view_offs == K -> view_offs )); 907 908const ggml_tensor * mask = dst -> src [3 ]; 909const ggml_tensor * sinks = dst -> src [4 ]; 910 911ggml_tensor * KQV = dst ; 912 913GGML_ASSERT (Q -> type == GGML_TYPE_F32 ); 914GGML_ASSERT (KQV -> type == GGML_TYPE_F32 ); 915 916GGML_ASSERT (Q -> nb [0 ]== ggml_element_size (Q )); 917GGML_ASSERT (K -> nb [0 ]== ggml_element_size (K )); 918GGML_ASSERT (V -> nb [0 ]== ggml_element_size (V )); 919 920GGML_ASSERT (!mask || mask -> type == GGML_TYPE_F16 ); 921 922ggml_sycl_pool & pool = ctx .pool (); 923ggml_sycl_fattn_kv_buffers & fbuf = ctx .fattn_buffers (); 924 dpct::queue_ptr main_stream = ctx .stream (); 925const int id = ggml_sycl_get_device (); 926const int nsm = ggml_sycl_info ().devices [id ].nsm ; 927 928ggml_sycl_fattn_alloc K_f16 (fbuf .K ); 929ggml_sycl_fattn_alloc V_f16 (fbuf .V ); 930const ggml_sycl_fattn_extra extra = ggml_sycl_fattn_get_extra (dst ); 931ggml_sycl_pool_alloc < int > KV_max (pool ); 932ggml_sycl_pool_alloc < float > dst_tmp (pool ); 933ggml_sycl_pool_alloc < sycl::float2 > dst_tmp_meta (pool ); 934 935const char * K_data = (const char * )K -> data ; 936size_t nb11 = K -> nb [1 ]; 937size_t nb12 = K -> nb [2 ]; 938size_t nb13 = K -> nb [3 ]; 939 940const char * V_data = (const char * )V -> data ; 941size_t nb21 = V -> nb [1 ]; 942size_t nb22 = V -> nb [2 ]; 943size_t nb23 = V -> nb [3 ]; 944 945if (need_f16_K && K -> type != GGML_TYPE_F16 ) { 946const size_t bs = ggml_blck_size (K -> type ); 947const size_t ts = ggml_type_size (K -> type ); 948 949 sycl::half * K_f16_ptr = extra .K_buffer_ptr ? (sycl::half * )extra .K_buffer_ptr 950 :K_f16 .alloc (ggml_nelements (K )); 951if (ggml_is_contiguously_allocated (K )) { 952to_fp16_sycl_t to_fp16 = ggml_get_to_fp16_sycl (K -> type ,dst ); 953to_fp16 (K_data ,K_f16_ptr ,ggml_nelements (K ),main_stream ); 954 955nb11 = nb11 * bs * sizeof (sycl::half ) /ts ; 956nb12 = nb12 * bs * sizeof (sycl::half ) /ts ; 957nb13 = nb13 * bs * sizeof (sycl::half ) /ts ; 958 }else { 959GGML_ASSERT (K -> nb [0 ]== ts ); 960to_fp16_nc_sycl_t to_fp16 = ggml_get_to_fp16_nc_sycl (K -> type ); 961const int64_t s01 = nb11 /ts ; 962const int64_t s02 = nb12 /ts ; 963const int64_t s03 = nb13 /ts ; 964to_fp16 (K_data ,K_f16_ptr ,K -> ne [0 ],K -> ne [1 ],K -> ne [2 ],K -> ne [3 ],s01 ,s02 ,s03 ,main_stream ); 965 966nb11 = K -> ne [0 ]* sizeof (sycl::half ); 967nb12 = K -> ne [1 ]* nb11 ; 968nb13 = K -> ne [2 ]* nb12 ; 969 } 970K_data = (char * )K_f16_ptr ; 971 } 972 973if (need_f16_V && V -> type != GGML_TYPE_F16 ) { 974if (V_is_K_view ) { 975V_data = K_data ; 976nb21 = nb11 ; 977nb22 = nb12 ; 978nb23 = nb13 ; 979 }else { 980const size_t bs = ggml_blck_size (V -> type ); 981const size_t ts = ggml_type_size (V -> type ); 982 983 sycl::half * V_f16_ptr = extra .V_buffer_ptr ? (sycl::half * )extra .V_buffer_ptr 984 :V_f16 .alloc (ggml_nelements (V )); 985if (ggml_is_contiguously_allocated (V )) { 986to_fp16_sycl_t to_fp16 = ggml_get_to_fp16_sycl (V -> type ,dst ); 987to_fp16 (V_data ,V_f16_ptr ,ggml_nelements (V ),main_stream ); 988V_data = (char * )V_f16_ptr ; 989 990nb21 = nb21 * bs * sizeof (sycl::half ) /ts ; 991nb22 = nb22 * bs * sizeof (sycl::half ) /ts ; 992nb23 = nb23 * bs * sizeof (sycl::half ) /ts ; 993 }else { 994GGML_ASSERT (V -> nb [0 ]== ts ); 995to_fp16_nc_sycl_t to_fp16 = ggml_get_to_fp16_nc_sycl (V -> type ); 996const int64_t s01 = nb21 /ts ; 997const int64_t s02 = nb22 /ts ; 998const int64_t s03 = nb23 /ts ; 999to_fp16 (V_data ,V_f16_ptr ,V -> ne [0 ],V -> ne [1 ],V -> ne [2 ],V -> ne [3 ],s01 ,s02 ,s03 ,main_stream ); 1000 1001nb21 = V -> ne [0 ]* sizeof (sycl::half ); 1002nb22 = V -> ne [1 ]* nb21 ; 1003nb23 = V -> ne [2 ]* nb22 ; 1004 } 1005V_data = (char * )V_f16_ptr ; 1006 } 1007 } 1008 1009const int ntiles_x = ((Q -> ne [1 ]+ ncols1 - 1 ) /ncols1 ); 1010const int gqa_ratio = Q -> ne [2 ] /K -> ne [2 ]; 1011const int ntiles_z_gqa = ((gqa_ratio + ncols2 - 1 ) /ncols2 ); 1012const int ntiles_total = ntiles_x * ntiles_z_gqa * K -> ne [2 ]* Q -> ne [3 ]; 1013 1014// Optional optimization where the mask is scanned to determine whether part of the calculation can be skipped. 1015// Only worth the overhead if there is at lease one FATTN_KQ_STRIDE x FATTN_KQ_STRIDE square to be skipped or 1016// multiple sequences of possibly different lengths. 1017if (mask && K -> ne [1 ] %FATTN_KQ_STRIDE == 0 && (Q -> ne [1 ] >=1024 || Q -> ne [3 ]> 1 )) { 1018const int s31 = mask -> nb [1 ] /sizeof (sycl::half2 ); 1019const int s33 = mask -> nb [3 ] /sizeof (sycl::half2 ); 1020 1021const dpct::dim3 blocks_num_KV_max (ntiles_x ,Q -> ne [3 ],1 ); 1022const dpct::dim3 block_dim_KV_max (FATTN_KQ_STRIDE /2 ,1 ,1 ); 1023 1024const int ne_KV_max = blocks_num_KV_max .x * blocks_num_KV_max .y ; 1025const int iter_k = K -> ne [1 ] /FATTN_KQ_STRIDE ; 1026 1027KV_max .alloc (ne_KV_max ); 1028 { 1029 dpct::has_capability_or_fail (main_stream -> get_device (), { sycl::aspect::fp16 }); 1030 1031main_stream -> submit ([& ](sycl::handler & cgh ) { 1032 sycl::local_accessor < int ,1 > buf_iw_acc_ct1 (sycl::range < 1 > (warp_size ),cgh ); 1033 1034auto mask_data_ct0 = (const sycl::half2 * )mask -> data ; 1035auto KV_max_ptr_ct1 = KV_max .ptr ; 1036 1037cgh .parallel_for (sycl::nd_range < 3 > (blocks_num_KV_max * block_dim_KV_max ,block_dim_KV_max ), 1038 [= ](sycl::nd_item < 3 > item_ct1 ) [[sycl ::reqd_sub_group_size (warp_size )]] { 1039GGML_UNUSED (item_ct1 ); 1040flash_attn_mask_to_KV_max < ncols1 ,warp_size > ( 1041mask_data_ct0 ,KV_max_ptr_ct1 ,iter_k ,s31 ,s33 , 1042buf_iw_acc_ct1 .get_multi_ptr < sycl::access::decorated::no > ().get ()); 1043 }); 1044 }); 1045 } 1046SYCL_CHECK (0 ); 1047 } 1048 1049const dpct::dim3 block_dim (warp_size ,nwarps ,1 ); 1050 1051// Max. number of active blocks limited by occupancy. 1052int max_blocks_per_sm = ggml_sycl_info ().devices [id ].max_wg_per_cu ; 1053int parallel_blocks = max_blocks_per_sm ; 1054 dpct::dim3 blocks_num ; 1055if (stream_k ) { 1056// For short contexts it can be faster to have the SMs work on whole tiles because this lets us skip the fixup. 1057const int max_blocks = max_blocks_per_sm * nsm ; 1058const int nblocks_stream_k = max_blocks ; 1059const bool use_stream_k = true; 1060 1061blocks_num .x = use_stream_k ?nblocks_stream_k :ntiles_total ; 1062blocks_num .y = 1 ; 1063blocks_num .z = 1 ; 1064 1065if (ntiles_total %blocks_num .x != 0 ) {// Fixup is only needed if the SMs work on fractional tiles. 1066dst_tmp_meta .alloc ((size_t (blocks_num .x )* ncols * (2 + DV /2 ))); 1067 } 1068 }else { 1069const int ntiles_KQ = (K -> ne [1 ]+ nbatch_fa - 1 ) /nbatch_fa ;// Max. number of parallel blocks limited by tensor size. 1070 1071// parallel_blocks must not be larger than what the tensor size allows: 1072parallel_blocks = std::min (parallel_blocks ,ntiles_KQ ); 1073// todo fix the hard code change 1074// parallel_blocks = ntiles_KQ; 1075 1076// If ntiles_total % blocks_per_wave != 0 then some efficiency is lost due to tail effects. 1077// Test whether parallel_blocks can be set to a higher value for better efficiency. 1078const int blocks_per_wave = nsm * max_blocks_per_sm ; 1079int nwaves_best = 0 ; 1080int efficiency_percent_best = 0 ; 1081for (int parallel_blocks_test = parallel_blocks ;parallel_blocks_test <=ntiles_KQ ;++ parallel_blocks_test ) { 1082const int nblocks_total = ntiles_total * parallel_blocks_test ; 1083const int nwaves = (nblocks_total + blocks_per_wave - 1 ) /blocks_per_wave ; 1084const int efficiency_percent = 100 * nblocks_total / (nwaves * blocks_per_wave ); 1085 1086// Stop trying configurations with more waves if we already have good efficiency to avoid excessive overhead. 1087if (efficiency_percent_best >=95 && nwaves > nwaves_best ) { 1088break ; 1089 } 1090 1091if (efficiency_percent > efficiency_percent_best ) { 1092nwaves_best = nwaves ; 1093efficiency_percent_best = efficiency_percent ; 1094parallel_blocks = parallel_blocks_test ; 1095 } 1096 } 1097 1098blocks_num .x = ntiles_x ; 1099blocks_num .y = parallel_blocks ; 1100blocks_num .z = ntiles_z_gqa * K -> ne [2 ]* Q -> ne [3 ]; 1101 1102if (parallel_blocks > 1 ) { 1103dst_tmp .alloc (parallel_blocks * ggml_nelements (KQV )); 1104dst_tmp_meta .alloc (parallel_blocks * ggml_nrows (KQV )); 1105 } 1106 } 1107 1108float scale = 1.0f ; 1109float max_bias = 0.0f ; 1110float logit_softcap = 0.0f ; 1111 1112memcpy (& scale , (const float * )KQV -> op_params + 0 ,sizeof (float )); 1113memcpy (& max_bias , (const float * )KQV -> op_params + 1 ,sizeof (float )); 1114memcpy (& logit_softcap , (const float * )KQV -> op_params + 2 ,sizeof (float )); 1115 1116if (logit_softcap != 0.0f ) { 1117scale /=logit_softcap ; 1118 } 1119 1120const uint32_t n_head = Q -> ne [2 ]; 1121const uint32_t n_head_log2 = 1u <<uint32_t (floorf (log2f (float (n_head )))); 1122 1123const float m0 = powf (2.0f ,- (max_bias ) /n_head_log2 ); 1124const float m1 = powf (2.0f ,- (max_bias /2.0f ) /n_head_log2 ); 1125 1126// TODO other tensor dimensions after removal of WMMA kernel: 1127const sycl::uint3 ne01 = init_fastdiv_values (Q -> ne [1 ]); 1128 1129GGML_ASSERT (block_dim .x %warp_size == 0 ); 1130 1131lauch_kernel < fattn_kernel ,warp_size > ( 1132blocks_num ,block_dim ,main_stream , (unsigned int )nbytes_shared , (const char * )Q -> data ,K_data ,V_data , 1133mask ? ((const char * )mask -> data ) :nullptr ,sinks ? ((const char * )sinks -> data ) :nullptr ,KV_max .ptr , 1134 !stream_k && parallel_blocks > 1 ?dst_tmp .ptr : (float * )KQV -> data , (sycl::float2 * )dst_tmp_meta .ptr ,scale ,max_bias ,m0 ,m1 , 1135n_head_log2 ,logit_softcap ,Q -> ne [0 ],ne01 ,Q -> ne [2 ],Q -> ne [3 ],Q -> nb [1 ],Q -> nb [2 ],Q -> nb [3 ],K -> ne [0 ], 1136K -> ne [1 ],K -> ne [2 ],K -> ne [3 ],nb11 ,nb12 ,nb13 ,nb21 ,nb22 ,nb23 ,mask ?mask -> ne [1 ] :0 , 1137mask ?mask -> ne [2 ] :0 ,mask ?mask -> ne [3 ] :0 ,mask ?mask -> nb [1 ] :0 ,mask ?mask -> nb [2 ] :0 , 1138mask ?mask -> nb [3 ] :0 ); 1139SYCL_CHECK (0 ); 1140 1141if (stream_k ) { 1142if (ntiles_total %blocks_num .x != 0 ) {// Fixup is only needed if the SMs work on fractional tiles. 1143const dpct::dim3 block_dim_combine (DV ,1 ,1 ); 1144const dpct::dim3 blocks_num_combine = {blocks_num .x ,ncols1 ,ncols2 }; 1145 1146main_stream -> submit ([& ](sycl::handler & cgh ) { 1147auto KQV_data_ct0 = (float * )KQV -> data ; 1148auto dst_tmp_meta_ptr_ct1 = dst_tmp_meta .ptr ; 1149auto Q_ne_ct2 = Q -> ne [1 ]; 1150auto Q_ne_ct3 = Q -> ne [2 ]; 1151auto Q_ne_ct4 = Q -> ne [3 ]; 1152auto K_ne_ct5 = K -> ne [1 ]; 1153auto K_ne_ct6 = K -> ne [2 ]; 1154 1155cgh .parallel_for (sycl::nd_range < 3 > (blocks_num_combine * block_dim_combine ,block_dim_combine ), 1156 [= ](sycl::nd_item < 3 > item_ct1 ) [[sycl ::reqd_sub_group_size (warp_size )]] { 1157GGML_UNUSED (item_ct1 ); 1158flash_attn_stream_k_fixup < DV ,ncols1 ,ncols2 > (KQV_data_ct0 ,dst_tmp_meta_ptr_ct1 , 1159Q_ne_ct2 ,Q_ne_ct3 ,Q_ne_ct4 , 1160K_ne_ct5 ,K_ne_ct6 ,nbatch_fa ); 1161 }); 1162 }); 1163 } 1164 }else if (parallel_blocks > 1 ) { 1165const dpct::dim3 block_dim_combine (DV ,1 ,1 ); 1166const dpct::dim3 blocks_num_combine (Q -> ne [1 ],Q -> ne [2 ],Q -> ne [3 ]); 1167const size_t nbytes_shared_combine = parallel_blocks * sizeof (sycl::float2 ); 1168main_stream -> submit ([& ](sycl::handler & cgh ) { 1169 sycl::local_accessor < uint8_t ,1 > dpct_local_acc_ct1 (sycl::range < 1 > (nbytes_shared_combine ),cgh ); 1170 1171auto dst_tmp_ptr_ct0 = dst_tmp .ptr ; 1172auto dst_tmp_meta_ptr_ct1 = dst_tmp_meta .ptr ; 1173auto KQV_data_ct2 = (float * )KQV -> data ; 1174 1175cgh .parallel_for (sycl::nd_range < 3 > (blocks_num_combine * block_dim_combine ,block_dim_combine ), 1176 [= ](sycl::nd_item < 3 > item_ct1 ) [[sycl ::reqd_sub_group_size (warp_size )]] { 1177GGML_UNUSED (item_ct1 ); 1178flash_attn_combine_results < DV > ( 1179dst_tmp_ptr_ct0 ,dst_tmp_meta_ptr_ct1 ,KQV_data_ct2 ,parallel_blocks , 1180dpct_local_acc_ct1 .get_multi_ptr < sycl::access::decorated::no > ().get ()); 1181 }); 1182 }); 1183 } 1184SYCL_CHECK (0 ); 1185}