char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
eef5f3e34
char/aliceai-t5-moe
1#ifndef GGML_SYCL_FATTN_VEC_HPP 2#define GGML_SYCL_FATTN_VEC_HPP 3 4#include <sycl/sycl.hpp> 5#include <sycl/ext/oneapi/work_group_static.hpp> 6#include <iostream> 7#include <iomanip> 8 9#include "dpct/helper.hpp" 10#include "common.hpp" 11#include "ggml.h" 12#include "fattn-common.hpp" 13#include <cmath> 14#include <float.h> 15 16namespace syclex= sycl::ext::oneapi::experimental; 17 18static int ggml_sycl_fattn_vec_get_nthreads_device (gpu_arch arch ) { 19// Xe2 (Battlemage, Lunar Lake) runs the flash-attention vec kernel best with a 256-thread work group. 20return (arch == gpu_arch::intel_gpu_bmg_g21 || 21arch == gpu_arch::intel_gpu_bmg_g31 || 22arch == gpu_arch::intel_gpu_lnl_m ) ?256 :128 ; 23} 24 25// Currenlty llvm with the amdgcn target dose not support unrolling loops 26// that contain a break that can not be resolved at compile time. 27#ifdef __clang__ 28#pragma clang diagnostic push 29#pragma clang diagnostic ignored "-Wpass-failed" 30#endif // __clang__ 31 32template < int D , 33int ncols , 34int type_K , 35int type_V , 36bool use_logit_softcap , 37int warp_size , 38int nthreads > // D == head size 39static void flash_attn_ext_vec (const char * __restrict__Q , 40const char * __restrict__K , 41const char * __restrict__V , 42const char * __restrict__mask , 43const char * __restrict__sinks , 44const int * __restrict__KV_max , 45float * __restrict__dst , 46 sycl::float2 * __restrict__dst_meta , 47const float scale , 48const float max_bias , 49const float m0 , 50const float m1 , 51const uint32_t n_head_log2 , 52const float logit_softcap , 53const int32_t ne00 , 54const sycl::uint3 ne01 , 55const int32_t ne02 , 56const int32_t ne03 , 57const int32_t nb01 , 58const int32_t nb02 , 59const int32_t nb03 , 60const int32_t ne10 , 61const int32_t ne11 , 62const int32_t ne12 , 63const int32_t ne13 , 64const int32_t nb11 , 65const int32_t nb12 , 66const int64_t nb13 , 67const int32_t nb21 , 68const int32_t nb22 , 69const int64_t nb23 , 70const int32_t ne31 , 71const int32_t ne32 , 72const int32_t ne33 , 73const int32_t nb31 , 74const int32_t nb32 , 75const int64_t nb33 ) { 76 77#ifdef SYCL_FLASH_ATTN 78// Skip unused kernel variants for faster compilation: 79 80auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 81if (use_logit_softcap && !(D == 128 || D == 256 )) { 82GGML_UNUSED_VARS (Q ,K ,V ,mask ,sinks ,KV_max ,dst ,dst_meta ,scale , 83max_bias ,m0 ,m1 ,n_head_log2 ,logit_softcap , 84ne00 ,ne01 ,ne02 ,ne03 , 85nb01 ,nb02 ,nb03 , 86ne10 ,ne11 ,ne12 ,ne13 , 87nb11 ,nb12 ,nb13 , 88nb21 ,nb22 ,nb23 , 89ne31 ,ne32 ,ne33 , 90nb31 ,nb32 ,nb33 ); 91return ; 92 } 93 94//In this kernel Q, K, V are matrices while i, j, k are matrix indices. 95 96constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes (); 97constexpr int cpy_ne = cpy_nb /4 ; 98 99constexpr int nthreads_KQ_q = (D /4 < warp_size ?D /4 :warp_size ); 100constexpr int nthreads_V_q = (D /4 < warp_size ?D /4 :warp_size ); 101 102constexpr int nthreads_KQ = type_K == GGML_TYPE_F16 ?128 /cpy_nb :nthreads_KQ_q ; 103constexpr int nthreads_V = type_V == GGML_TYPE_F16 ?128 /cpy_nb :nthreads_V_q ; 104 105 static_assert(warp_size %nthreads_KQ == 0 ,"bad nthreads_K" ); 106 static_assert(warp_size %nthreads_V == 0 ,"bad nthreads_V" ); 107 108constexpr int V_rows_per_thread = type_V == GGML_TYPE_F16 ?2 * cpy_ne :4 ; 109constexpr int V_cols_per_iter = warp_size /nthreads_V ; 110 111constexpr vec_dot_KQ_t vec_dot_KQ = get_vec_dot_KQ < type_K ,D ,nthreads_KQ ,warp_size > (); 112constexpr bool Q_q8_1 = type_K != GGML_TYPE_F16 ; 113#ifdef GGML_SYCL_F16 114constexpr dequantize_V_t dequantize_V = get_dequantize_V < type_V , sycl::half ,V_rows_per_thread > (); 115#else 116constexpr dequantize_V_t dequantize_V = get_dequantize_V < type_V ,float ,V_rows_per_thread > (); 117#endif // GGML_SYCL_F16 118 119const int ic0 = item_ct1 .get_group (2 )* ncols ;// Index of the Q/QKV column to work on. 120 121const int sequence = item_ct1 .get_group (0 ) /ne02 ; 122const int head = item_ct1 .get_group (0 )- sequence * ne02 ; 123const int gqa_ratio = ne02 /ne12 ;// With grouped query attention there are > 1 Q matrices per K, V matrix. 124Q += nb03 * sequence + nb02 * head + nb01 * ic0 ; 125K += nb13 * sequence + nb12 * (head /gqa_ratio ); 126V += nb23 * sequence + nb22 * (head /gqa_ratio ); 127 128const sycl::half * maskh = (const sycl::half * ) (mask + nb33 * (sequence %ne33 )+ nb31 * ic0 ); 129 130const float slope = get_alibi_slope (max_bias ,head ,n_head_log2 ,m0 ,m1 ); 131 132 static_assert(D % (2 * warp_size )== 0 ,"D not divisible by 2*warp_size == 64." ); 133constexpr int nwarps = nthreads /warp_size ; 134const int tid = warp_size * item_ct1 .get_local_id (1 )+ item_ct1 .get_local_id (2 ); 135__builtin_assume (tid < nthreads ); 136 137constexpr int ne_KQ = ncols * D ; 138constexpr int ne_combine = nwarps * V_cols_per_iter * D ; 139 140constexpr size_t lsm_size1 = ncols * warp_size ; 141constexpr size_t lsm_size2 = ncols * warp_size ; 142#ifdef GGML_SYCL_F16 143 sycl::half2 VKQ [ncols ][(D /2 ) /nthreads_V ]= { { {0.0f ,0.0f } } }; 144constexpr size_t lsm_size3 = (ne_KQ > ne_combine ?ne_KQ :ne_combine ); 145constexpr size_t local_share_mem_size = (lsm_size1 + lsm_size2 )* sizeof (float )+ lsm_size3 * sizeof (sycl::half ); 146 147 syclex::work_group_static < char [local_share_mem_size ]> lsm ; 148 149float * KQ_max_shared = (float * )& lsm ; 150float * KQ_sum_shared = KQ_max_shared + lsm_size1 ; 151 sycl::half * KQ = (sycl::half * )(KQ_sum_shared + lsm_size2 ); 152 153 154#else 155 sycl::float2 VKQ [ncols ][(D /2 )/nthreads_V ]= {{{0.0f ,0.0f }}}; 156 157constexpr size_t lsm_size3 = (ne_KQ > ne_combine ?ne_KQ :ne_combine ); 158constexpr size_t local_share_mem_size = (lsm_size1 + lsm_size2 + lsm_size3 )* sizeof (float ); 159 160 161 syclex::work_group_static < char [local_share_mem_size ]> lsm ; 162float * KQ_max_shared = (float * )& lsm ; 163float * KQ_sum_shared = KQ_max_shared + lsm_size1 ; 164float * KQ = KQ_sum_shared + lsm_size2 ; 165 166#endif // GGML_SYCL_F16 167 168float KQ_max [ncols ]; 169float KQ_sum [ncols ]; 170#pragma unroll 171for (int j = 0 ;j < ncols ;++ j ) { 172KQ_max [j ]= - FLT_MAX /2.0f ; 173KQ_sum [j ]= 0.0f ; 174 } 175 176// Convert Q to float2 (f16 K) or q8_1 (quantized K) and store in registers: 177#ifdef GGML_SYCL_F16 178 sycl::half2 Q_reg [ncols ][(D /2 ) /nthreads_KQ ]= {{{0.0f ,0.0f }}};// Will be initialized completely. 179#else 180 sycl::float2 Q_reg [ncols ][(D /2 )/nthreads_KQ ]= {{{0.0f ,0.0f }}};// May be only partially initialized. 181#endif // GGML_SYCL_F16 182int Q_i32 [ncols ][1 > D /(sizeof (int )* nthreads_KQ ) ?1 :D /(sizeof (int )* nthreads_KQ )]; 183 sycl::float2 Q_ds [ncols ][1 > D / (sizeof (int )* nthreads_KQ ) ?1 :D / (sizeof (int )* nthreads_KQ )]; 184if constexpr (Q_q8_1 ) { 185#pragma unroll 186for (int j0 = 0 ;j0 < ncols ;j0 += nwarps ) { 187const int j = j0 + item_ct1 .get_local_id (1 ); 188 189if (j0 + nwarps > ncols && j >=ncols ) { 190break ; 191 } 192 193// Reuse KQ as temporary storage for converting Q to q8_1: 194int * tmp_q_i32 = (int * )& KQ [j * D ]; 195 sycl::float2 * tmp_q_ds = (sycl::float2 * ) (tmp_q_i32 + D /sizeof (int )); 196 197// Set memory to zero if out of bounds: 198if (ncols > 1 && ic0 + j >=int (ne01 .z ())) { 199#pragma unroll 200for (int i0 = 0 ;i0 < int (D /sizeof (int ));i0 += warp_size ) { 201const int i = i0 + item_ct1 .get_local_id (2 ); 202 203if (i0 + warp_size <=int (D /sizeof (int ))|| i < int (D /sizeof (int ))) { 204tmp_q_i32 [i ]= 0 ; 205 } 206 } 207if (item_ct1 .get_local_id (2 )< D /QK8_1 ) { 208tmp_q_ds [item_ct1 .get_local_id (2 )]= sycl::float2 (0.0f ,0.0f ); 209 } 210 }else { 211const float * Q_f = (const float * ) (Q + j * nb01 ); 212constexpr int nthreads_quantize = D /sizeof (int )< warp_size ?D /sizeof (int ) :warp_size ; 213#pragma unroll 214for (int i0 = 0 ;i0 < int (D /sizeof (int ));i0 += nthreads_quantize ) { 215quantize_q8_1_to_shared < sycl::float2 ,nthreads_quantize ,warp_size > 216 (Q_f + i0 * sizeof (int ),scale ,tmp_q_i32 + i0 ,tmp_q_ds + i0 /QI8_1 ); 217 } 218 } 219 } 220 221 222item_ct1 .barrier (sycl::access::fence_space::local_space ); 223 224#pragma unroll 225for (int j = 0 ;j < ncols ;++ j ) { 226int * tmp_q_i32 = (int * )& KQ [j * D ]; 227 sycl::float2 * tmp_q_ds = (sycl::float2 * ) (tmp_q_i32 + D /sizeof (int )); 228 229#pragma unroll 230for (int i0 = 0 ;i0 < int (D /sizeof (int ));i0 += nthreads_KQ ) { 231const int i = 232i0 + (nthreads_KQ == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads_KQ ); 233 234Q_i32 [j ][i0 /nthreads_KQ ]= tmp_q_i32 [i ]; 235Q_ds [j ][i0 /nthreads_KQ ]= tmp_q_ds [i /QI8_1 ]; 236 } 237 } 238 239item_ct1 .barrier (sycl::access::fence_space::local_space ); 240 241 }else { 242#ifdef GGML_SYCL_F16 243const sycl::half2 scale_h2 = sycl::half2 (scale ,scale ); 244#pragma unroll 245for (int j = 0 ;j < ncols ;++ j ) { 246const sycl::float2 * Q_j = (const sycl::float2 * ) (Q + j * nb01 ); 247#pragma unroll 248for (int i0 = 0 ;i0 < D /2 ;i0 += nthreads_KQ * cpy_ne ) { 249const int i = i0 + (nthreads_KQ == warp_size ?item_ct1 .get_local_id (2 ) : 250item_ct1 .get_local_id (2 ) %nthreads_KQ )* 251cpy_ne ; 252 253 sycl::float2 tmp [cpy_ne ]= { 254 {0.0f ,0.0f } 255 }; 256if (ncols == 1 || ic0 + j < int (ne01 .z ())) { 257ggml_sycl_memcpy_1 < cpy_nb > (tmp ,& Q_j [i ]); 258ggml_sycl_memcpy_1 < cpy_nb > (tmp + cpy_ne /2 ,& Q_j [i + cpy_ne /2 ]); 259 } 260#pragma unroll 261for (int i1 = 0 ;i1 < cpy_ne ;++ i1 ) { 262Q_reg [j ][i0 /nthreads_KQ + i1 ]= sycl::half2 (tmp [i1 ].x (),tmp [i1 ].y ()); 263 } 264 } 265#pragma unroll 266for (int k = 0 ;k < (D /2 )/nthreads_KQ ;++ k ) { 267Q_reg [j ][k ] *=scale_h2 ; 268 } 269 } 270#else 271#pragma unroll 272for (int j = 0 ;j < ncols ;++ j ) { 273const sycl::float2 * Q_j = (const sycl::float2 * ) (Q + j * nb01 ); 274#pragma unroll 275for (int i0 = 0 ;i0 < D /2 ;i0 += nthreads_KQ * cpy_ne ) { 276const int i = i0 + (nthreads_KQ == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads_KQ )* cpy_ne ; 277if (ncols == 1 || ic0 + j < int (ne01 .z ())) { 278ggml_sycl_memcpy_1 < cpy_nb > (& Q_reg [j ][i0 /nthreads_KQ ],& Q_j [i ]); 279ggml_sycl_memcpy_1 < cpy_nb > (& Q_reg [j ][i0 /nthreads_KQ + cpy_ne /2 ],& Q_j [i + cpy_ne /2 ]); 280 } 281 } 282#pragma unroll 283for (int k = 0 ;k < (D /2 )/nthreads_KQ ;++ k ) { 284Q_reg [j ][k ].x () *=scale ; 285Q_reg [j ][k ].y () *=scale ; 286 } 287 } 288#endif // GGML_SYCL_F16 289 } 290 291const int k_VKQ_max = KV_max ?KV_max [sequence * item_ct1 .get_group_range (2 )+ item_ct1 .get_group (2 )] :ne11 ; 292K += item_ct1 .get_group (1 )* nthreads * nb11 ; 293V += item_ct1 .get_group (1 )* nthreads * nb21 ; 294maskh += item_ct1 .get_group (1 )* nthreads ; 295for (int k_VKQ_0 = item_ct1 .get_group (1 )* nthreads ;k_VKQ_0 < k_VKQ_max ; 296k_VKQ_0 += item_ct1 .get_group_range (1 )* nthreads , 297// Increment pointers after each loop: 298K += item_ct1 .get_group_range (1 )* nthreads * nb11 ,V += item_ct1 .get_group_range (1 )* nthreads * nb21 , 299maskh += item_ct1 .get_group_range (1 )* nthreads ) { 300// Calculate KQ tile and keep track of new maximum KQ values: 301float KQ_reg [ncols ]= {};// KQ in registers. 302float KQ_max_new [ncols ]= {}; 303 304 305#pragma unroll 306for (int j = 0 ;j < ncols ;++ j ) { 307KQ_max_new [j ]= KQ_max [j ]; 308 } 309 310#pragma unroll 311for (int i_KQ_0 = 0 ;i_KQ_0 < nthreads_KQ ;++ i_KQ_0 ) { 312const int i_KQ = item_ct1 .get_local_id (1 )* warp_size + 313 (nthreads_KQ == warp_size ?0 : (item_ct1 .get_local_id (2 )& ~(nthreads_KQ - 1 )))+ i_KQ_0 ; 314 315#pragma unroll 316for (int j = 0 ;j < ncols ;++ j ) { 317float sum = vec_dot_KQ (K + i_KQ * nb11 ,Q_reg [j ],Q_i32 [j ],Q_ds [j ]); 318sum = warp_reduce_sum < nthreads_KQ > (sum ); 319 320if (use_logit_softcap ) { 321sum = logit_softcap * sycl::tanh (sum ); 322 } 323if (mask ) { 324sum += slope * sycl::vec < sycl::half ,1 > (maskh [j * ne11 + i_KQ ]) 325 .convert < float , sycl::rounding_mode::automatic > ()[0 ]; 326 } 327 328KQ_max_new [j ]= sycl::fmax ((float )KQ_max_new [j ],sum ); 329 330if (int (nthreads_KQ == warp_size ?item_ct1 .get_local_id (2 ) 331 :item_ct1 .get_local_id (2 ) % 332nthreads_KQ )== i_KQ_0 ) { 333KQ_reg [j ]= sum ; 334 } 335 } 336 } 337 338#pragma unroll 339for (int j = 0 ;j < ncols ;++ j ) { 340#pragma unroll 341for (int offset = nthreads_KQ ;offset < warp_size ;offset <<=1 ) { 342KQ_max_new [j ]= sycl::fmax ( 343 (float )KQ_max_new [j ], 344 (float )dpct::permute_sub_group_by_xor ( 345 sycl::ext::oneapi::this_work_item::get_sub_group (), 346KQ_max_new [j ], 347offset , 348warp_size )); 349 } 350const float KQ_max_scale = sycl::native::exp ((float ) (KQ_max [j ]- KQ_max_new [j ])); 351KQ_max [j ]= KQ_max_new [j ]; 352 353KQ_reg [j ]= sycl::native::exp ((float ) (KQ_reg [j ]- KQ_max [j ])); 354KQ_sum [j ]= KQ_sum [j ]* KQ_max_scale + KQ_reg [j ]; 355KQ [j * nthreads + tid ]= KQ_reg [j ]; 356 357#ifdef GGML_SYCL_F16 358const sycl::half2 KQ_max_scale_h2 = sycl::half2 (KQ_max_scale ,KQ_max_scale ); 359#pragma unroll 360for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V ) { 361VKQ [j ][i_VKQ_0 /nthreads_V ] *=KQ_max_scale_h2 ; 362 } 363#else 364#pragma unroll 365for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V ) { 366VKQ [j ][i_VKQ_0 /nthreads_V ].x () *=KQ_max_scale ; 367VKQ [j ][i_VKQ_0 /nthreads_V ].y () *=KQ_max_scale ; 368 } 369#endif // GGML_SYCL_F16 370 } 371 372 sycl::group_barrier (sycl::ext::oneapi::this_work_item::get_sub_group ()); 373 374#pragma unroll 375for (int k0 = 0 ;k0 < warp_size ;k0 += V_cols_per_iter ) { 376const int k = item_ct1 .get_local_id (1 )* warp_size + k0 + 377 (nthreads_V == warp_size ?0 :item_ct1 .get_local_id (2 ) /nthreads_V ); 378 379#ifdef GGML_SYCL_F16 380 sycl::half2 KQ_k [ncols ]; 381#pragma unroll 382for (int j = 0 ;j < ncols ;++ j ) { 383KQ_k [j ]= sycl::half2 (KQ [j * nthreads + k ]); 384 } 385#pragma unroll 386for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V * V_rows_per_thread /2 ) { 387 sycl::half2 tmp [V_rows_per_thread /2 ]; 388dequantize_V (V + k * nb21 ,tmp , 3892 * i_VKQ_0 + (nthreads_V == warp_size ?item_ct1 .get_local_id (2 ) : 390item_ct1 .get_local_id (2 ) %nthreads_V )* 391V_rows_per_thread ); 392#pragma unroll 393for (int i_VKQ_1 = 0 ;i_VKQ_1 < V_rows_per_thread /2 ;++ i_VKQ_1 ) { 394#pragma unroll 395for (int j = 0 ;j < ncols ;++ j ) { 396VKQ [j ][i_VKQ_0 /nthreads_V + i_VKQ_1 ]+= tmp [i_VKQ_1 ]* KQ_k [j ]; 397 } 398 } 399 } 400#else 401float KQ_k [ncols ]; 402#pragma unroll 403for (int j = 0 ;j < ncols ;++ j ) { 404KQ_k [j ]= KQ [j * nthreads + k ]; 405 } 406#pragma unroll 407for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V * V_rows_per_thread /2 ) { 408 sycl::float2 tmp [V_rows_per_thread /2 ]; 409dequantize_V (V + k * nb21 ,tmp , 4102 * i_VKQ_0 + (nthreads_V == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads_V )* V_rows_per_thread ); 411#pragma unroll 412for (int i_VKQ_1 = 0 ;i_VKQ_1 < V_rows_per_thread /2 ;++ i_VKQ_1 ) { 413#pragma unroll 414for (int j = 0 ;j < ncols ;++ j ) { 415VKQ [j ][i_VKQ_0 /nthreads_V + i_VKQ_1 ].x ()+= tmp [i_VKQ_1 ].x ()* KQ_k [j ]; 416VKQ [j ][i_VKQ_0 /nthreads_V + i_VKQ_1 ].y ()+= tmp [i_VKQ_1 ].y ()* KQ_k [j ]; 417 } 418 } 419 } 420#endif // GGML_SYCL_F16 421 } 422 } 423 424if (sinks && item_ct1 .get_group (1 )== 0 ) { 425const float sink = ((const float * )sinks )[head ]; 426 427#pragma unroll 428for (int j0 = 0 ;j0 < ncols ;j0 += nwarps ) { 429const int j = j0 + item_ct1 .get_local_id (1 ); 430 431if (j0 + nwarps > ncols && j >=ncols ) { 432break ; 433 } 434const float kqmax_new_j = sycl::fmax (sink , (float )KQ_max [j ]); 435const float KQ_max_scale = sycl::native::exp ((float ) (KQ_max [j ]- kqmax_new_j )); 436KQ_max [j ]= kqmax_new_j ; 437 438KQ_sum [j ]= KQ_sum [j ]* KQ_max_scale + 439 (item_ct1 .get_local_id (2 )== 0 ? sycl::native::exp ((float ) (sink - KQ_max [j ])) :0.0f ); 440#ifdef GGML_SYCL_F16 441const sycl::half2 KQ_max_scale_h2 = sycl::half2 (KQ_max_scale ,KQ_max_scale ); 442#pragma unroll 443for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V ) { 444VKQ [j ][i_VKQ_0 /nthreads_V ] *=KQ_max_scale_h2 ; 445 } 446#else 447#pragma unroll 448for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V ) { 449VKQ [j ][i_VKQ_0 /nthreads_V ].x () *=KQ_max_scale ; 450VKQ [j ][i_VKQ_0 /nthreads_V ].y () *=KQ_max_scale ; 451 } 452#endif // GGML_SYCL_F16 453 } 454 } 455 456#pragma unroll 457for (int j = 0 ;j < ncols ;++ j ) { 458if (item_ct1 .get_local_id (1 )== 0 ) { 459KQ_max_shared [j * warp_size + item_ct1 .get_local_id (2 )]= - FLT_MAX /2.0f ; 460KQ_sum_shared [j * warp_size + item_ct1 .get_local_id (2 )]= 0.0f ; 461 } 462 } 463 464item_ct1 .barrier (sycl::access::fence_space::local_space ); 465 466#pragma unroll 467for (int j = 0 ;j < ncols ;++ j ) { 468if (item_ct1 .get_local_id (2 )== 0 ) { 469KQ_max_shared [j * warp_size + item_ct1 .get_local_id (1 )]= KQ_max [j ]; 470 } 471 } 472 473item_ct1 .barrier (sycl::access::fence_space::local_space ); 474 475#pragma unroll 476for (int j_VKQ = 0 ;j_VKQ < ncols ;++ j_VKQ ) { 477if (ncols > 1 && ic0 + j_VKQ >=int (ne01 .z ())) { 478break ; 479 } 480 481float kqmax_new = KQ_max_shared [j_VKQ * warp_size + item_ct1 .get_local_id (2 )]; 482kqmax_new = warp_reduce_max < warp_size > (kqmax_new ); 483const float kqmax_scale = sycl::native::exp ((float ) (KQ_max [j_VKQ ]- kqmax_new )); 484KQ_max [j_VKQ ]= kqmax_new ; 485 486#ifdef GGML_SYCL_F16 487 sycl::half2 * VKQ_tmp = (sycl::half2 * )KQ + item_ct1 .get_local_id (1 )* (V_cols_per_iter * D /2 )+ 488 (nthreads_V == warp_size ?0 :item_ct1 .get_local_id (2 ) /nthreads_V )* (D /2 ); 489 490const sycl::half2 kqmax_scale_h2 = sycl::half2 (kqmax_scale ,kqmax_scale ); 491#pragma unroll 492for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V ) { 493VKQ [j_VKQ ][i_VKQ_0 /nthreads_V ] *=kqmax_scale_h2 ; 494 } 495#pragma unroll 496for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V * V_rows_per_thread /2 ) { 497const int i_VKQ = 498i_VKQ_0 + (nthreads_V == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads_V )* 499 (V_rows_per_thread /2 ); 500 501ggml_sycl_memcpy_1 < V_rows_per_thread * sizeof (sycl::half )> (VKQ_tmp + i_VKQ , 502& VKQ [j_VKQ ][i_VKQ_0 /nthreads_V ]); 503 } 504#else 505 sycl::float2 * VKQ_tmp = (sycl::float2 * )KQ + item_ct1 .get_local_id (1 )* (V_cols_per_iter * D /2 ) 506+ (nthreads_V == warp_size ?0 :item_ct1 .get_local_id (2 ) /nthreads_V )* (D /2 ); 507#pragma unroll 508for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V ) { 509VKQ [j_VKQ ][i_VKQ_0 /nthreads_V ].x () *=kqmax_scale ; 510VKQ [j_VKQ ][i_VKQ_0 /nthreads_V ].y () *=kqmax_scale ; 511 } 512#pragma unroll 513for (int i_VKQ_0 = 0 ;i_VKQ_0 < D /2 ;i_VKQ_0 += nthreads_V * V_rows_per_thread /2 ) { 514const int i_VKQ = i_VKQ_0 + (nthreads_V == warp_size ?item_ct1 .get_local_id (2 ) :item_ct1 .get_local_id (2 ) %nthreads_V )* (V_rows_per_thread /2 ); 515 516ggml_sycl_memcpy_1 < V_rows_per_thread /2 * sizeof (float )> (VKQ_tmp + i_VKQ ,& VKQ [j_VKQ ][i_VKQ_0 /nthreads_V ]); 517ggml_sycl_memcpy_1 < V_rows_per_thread /2 * sizeof (float )> (VKQ_tmp + i_VKQ + V_rows_per_thread /4 ,& VKQ [j_VKQ ][i_VKQ_0 /nthreads_V + V_rows_per_thread /4 ]); 518 } 519#endif // GGML_SYCL_F16 520 521KQ_sum [j_VKQ ] *=kqmax_scale ; 522KQ_sum [j_VKQ ]= warp_reduce_sum < warp_size > (KQ_sum [j_VKQ ]); 523if (item_ct1 .get_local_id (2 )== 0 ) { 524KQ_sum_shared [j_VKQ * warp_size + item_ct1 .get_local_id (1 )]= KQ_sum [j_VKQ ]; 525 } 526 527item_ct1 .barrier (sycl::access::fence_space::local_space ); 528 529 530if (nthreads <=D || tid < D ) { 531KQ_sum [j_VKQ ]= KQ_sum_shared [j_VKQ * warp_size + item_ct1 .get_local_id (2 )]; 532KQ_sum [j_VKQ ]= warp_reduce_sum < warp_size > (KQ_sum [j_VKQ ]); 533 534#pragma unroll 535for (int i0 = 0 ;i0 < D ;i0 += nthreads ) { 536float dst_val = 0 ; 537#pragma unroll 538for (int w = 0 ;w < nwarps ;++ w ) { 539#pragma unroll 540for (int v = 0 ;v < V_cols_per_iter ;++ v ) { 541dst_val += float (KQ [w * V_cols_per_iter * D + v * D + i0 + tid ]); 542 } 543 } 544if (item_ct1 .get_group_range (1 )== 1 ) { 545dst_val /=KQ_sum [j_VKQ ]; 546 } 547dst [(((sequence * int (ne01 .z ())+ ic0 + j_VKQ )* ne02 + head )* item_ct1 .get_group_range (1 )+ 548item_ct1 .get_group (1 ))* 549D + 550i0 + tid ]= dst_val ; 551 } 552 } 553 554if (j_VKQ < ncols - 1 ) { 555item_ct1 .barrier (sycl::access::fence_space::local_space ); 556 } 557 558 } 559 560if (item_ct1 .get_group_range (1 )!= 1 && tid < ncols && (ncols == 1 || ic0 + tid < int (ne01 .z ()))) { 561dst_meta [((sequence * int (ne01 .z ())+ ic0 + tid )* ne02 + head )* item_ct1 .get_group_range (1 )+ 562item_ct1 .get_group (1 )]= make_float2 (KQ_max [tid ],KQ_sum [tid ]); 563 } 564#else 565GGML_UNUSED_VARS (Q ,K ,V ,mask ,sinks ,KV_max ,dst ,dst_meta ,scale , 566max_bias ,m0 ,m1 ,n_head_log2 ,logit_softcap , 567ne00 ,ne01 ,ne02 ,ne03 , 568nb01 ,nb02 ,nb03 , 569ne10 ,ne11 ,ne12 ,ne13 , 570nb11 ,nb12 ,nb13 , 571nb21 ,nb22 ,nb23 , 572ne31 ,ne32 ,ne33 , 573nb31 ,nb32 ,nb33 ); 574 575#endif // SYCL_FLASH_ATTN 576} 577#ifdef __clang__ 578#pragma clang diagnostic pop 579#endif // __clang__ 580 581 582 583template < int D ,int cols_per_block ,int type_K ,int type_V ,bool use_logit_softcap > 584void ggml_sycl_flash_attn_ext_vec_case_impl (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 585 586constexpr int warp_size = WARP_16_SIZE ;//better performance than WARP_32_SIZE 587 588const bool need_f16_K = type_K == GGML_TYPE_F16 ; 589const bool need_f16_V = type_V == GGML_TYPE_F16 ; 590constexpr size_t nbytes_shared = 0 ; 591 592const auto arch = ggml_sycl_info ().devices [ctx .device ].hw_info .arch ; 593const int nthreads = ggml_sycl_fattn_vec_get_nthreads_device (arch ); 594if constexpr (D <=256 ) { 595if (nthreads == 256 ) { 596constexpr int nthreads_hw = 256 ; 597constexpr int nwarps = nthreads_hw /warp_size ; 598launch_fattn < D ,cols_per_block ,1 , 599flash_attn_ext_vec < D ,cols_per_block ,type_K ,type_V , 600use_logit_softcap ,warp_size ,nthreads_hw > ,warp_size > ( 601ctx ,dst ,nwarps ,nbytes_shared ,D ,need_f16_K ,need_f16_V , false); 602return ; 603 } 604 } 605 606constexpr int nthreads_hw = 128 ; 607constexpr int nwarps = nthreads_hw /warp_size ; 608launch_fattn < D ,cols_per_block ,1 , 609flash_attn_ext_vec < D ,cols_per_block ,type_K ,type_V , 610use_logit_softcap ,warp_size ,nthreads_hw > ,warp_size > ( 611ctx ,dst ,nwarps ,nbytes_shared ,D ,need_f16_K ,need_f16_V , false); 612} 613 614template < int D ,int type_K ,int type_V > 615void ggml_sycl_flash_attn_ext_vec_case (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 616const ggml_tensor * KQV = dst ; 617const ggml_tensor * Q = dst -> src [0 ]; 618 619float logit_softcap ; 620memcpy (& logit_softcap , (const float * )KQV -> op_params + 2 ,sizeof (float )); 621 622if (Q -> ne [1 ]== 1 ) { 623constexpr int cols_per_block = 1 ; 624if (logit_softcap == 0.0f ) { 625constexpr bool use_logit_softcap = false; 626ggml_sycl_flash_attn_ext_vec_case_impl < D ,cols_per_block ,type_K ,type_V ,use_logit_softcap > (ctx ,dst ); 627 }else { 628constexpr bool use_logit_softcap = true; 629ggml_sycl_flash_attn_ext_vec_case_impl < D ,cols_per_block ,type_K ,type_V ,use_logit_softcap > (ctx ,dst ); 630 } 631return ; 632 } 633 634constexpr int cols_per_block = 2 ; 635if (logit_softcap == 0.0f ) { 636constexpr bool use_logit_softcap = false; 637ggml_sycl_flash_attn_ext_vec_case_impl < D ,cols_per_block ,type_K ,type_V ,use_logit_softcap > (ctx ,dst ); 638 }else { 639constexpr bool use_logit_softcap = true; 640ggml_sycl_flash_attn_ext_vec_case_impl < D ,cols_per_block ,type_K ,type_V ,use_logit_softcap > (ctx ,dst ); 641 } 642} 643 644#define DECL_FATTN_VEC_CASE (D ,type_K ,type_V ) \ 645 template void ggml_sycl_flash_attn_ext_vec_case \ 646 <D, type_K, type_V>(ggml_backend_sycl_context & ctx, ggml_tensor * dst) \ 647 648#define EXTERN_DECL_FATTN_VEC_CASES (D ,type_K ) \ 649 extern DECL_FATTN_VEC_CASE(D, type_K, GGML_TYPE_F16); \ 650 extern DECL_FATTN_VEC_CASE(D, type_K, GGML_TYPE_Q4_0); \ 651 extern DECL_FATTN_VEC_CASE(D, type_K, GGML_TYPE_Q4_1); \ 652 extern DECL_FATTN_VEC_CASE(D, type_K, GGML_TYPE_Q5_0); \ 653 extern DECL_FATTN_VEC_CASE(D, type_K, GGML_TYPE_Q5_1); \ 654 extern DECL_FATTN_VEC_CASE(D, type_K, GGML_TYPE_Q8_0); \ 655 656EXTERN_DECL_FATTN_VEC_CASES (64 ,GGML_TYPE_F16 ) 657EXTERN_DECL_FATTN_VEC_CASES (64 ,GGML_TYPE_Q4_0 ) 658EXTERN_DECL_FATTN_VEC_CASES (64 ,GGML_TYPE_Q4_1 ) 659EXTERN_DECL_FATTN_VEC_CASES (64 ,GGML_TYPE_Q5_0 ) 660EXTERN_DECL_FATTN_VEC_CASES (64 ,GGML_TYPE_Q5_1 ) 661EXTERN_DECL_FATTN_VEC_CASES (64 ,GGML_TYPE_Q8_0 ) 662 663EXTERN_DECL_FATTN_VEC_CASES (128 ,GGML_TYPE_F16 ) 664EXTERN_DECL_FATTN_VEC_CASES (128 ,GGML_TYPE_Q4_0 ) 665EXTERN_DECL_FATTN_VEC_CASES (128 ,GGML_TYPE_Q4_1 ) 666EXTERN_DECL_FATTN_VEC_CASES (128 ,GGML_TYPE_Q5_0 ) 667EXTERN_DECL_FATTN_VEC_CASES (128 ,GGML_TYPE_Q5_1 ) 668EXTERN_DECL_FATTN_VEC_CASES (128 ,GGML_TYPE_Q8_0 ) 669 670EXTERN_DECL_FATTN_VEC_CASES (256 ,GGML_TYPE_F16 ) 671EXTERN_DECL_FATTN_VEC_CASES (256 ,GGML_TYPE_Q4_0 ) 672EXTERN_DECL_FATTN_VEC_CASES (256 ,GGML_TYPE_Q4_1 ) 673EXTERN_DECL_FATTN_VEC_CASES (256 ,GGML_TYPE_Q5_0 ) 674EXTERN_DECL_FATTN_VEC_CASES (256 ,GGML_TYPE_Q5_1 ) 675EXTERN_DECL_FATTN_VEC_CASES (256 ,GGML_TYPE_Q8_0 ) 676 677EXTERN_DECL_FATTN_VEC_CASES (512 ,GGML_TYPE_F16 ) 678EXTERN_DECL_FATTN_VEC_CASES (512 ,GGML_TYPE_Q4_0 ) 679EXTERN_DECL_FATTN_VEC_CASES (512 ,GGML_TYPE_Q4_1 ) 680EXTERN_DECL_FATTN_VEC_CASES (512 ,GGML_TYPE_Q5_0 ) 681EXTERN_DECL_FATTN_VEC_CASES (512 ,GGML_TYPE_Q5_1 ) 682EXTERN_DECL_FATTN_VEC_CASES (512 ,GGML_TYPE_Q8_0 ) 683 684#endif // GGML_SYCL_FATTN_VEC_HPP