char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
3d9388535
char/aliceai-t5-moe
1#include <sycl/sycl.hpp> 2#include "dpct/helper.hpp" 3#include "common.hpp" 4#include "ggml.h" 5#include "gated_delta_net.hpp" 6#include <cmath> 7 8 9template < int S_v ,bool KDA ,bool keep_rs_t > 10void gated_delta_net_sycl (const float * q , 11const float * k , 12const float * v , 13const float * g , 14const float * beta , 15const float * curr_state , 16float * dst , 17float * state , 18int64_t H , 19int64_t n_tokens , 20int64_t sq1 , 21int64_t sq2 , 22int64_t sq3 , 23int64_t sv1 , 24int64_t sv2 , 25int64_t sv3 , 26int64_t sb1 , 27int64_t sb2 , 28int64_t sb3 , 29const sycl::uint3 neqk1_magic , 30const sycl::uint3 rq3_magic , 31float scale , 32int64_t state_slot_stride , 33int K ) { 34auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 35const uint32_t h_idx = item_ct1 .get_group (2 ); 36const uint32_t sequence = item_ct1 .get_group (1 ); 37// each warp owns one column, using warp-level primitives to reduce across rows 38const int lane = item_ct1 .get_local_id (2 ); 39const int col = item_ct1 .get_group (0 )* item_ct1 .get_local_range (1 )+ item_ct1 .get_local_id (1 ); 40 41const uint32_t iq1 = fastmodulo (h_idx ,neqk1_magic ); 42const uint32_t iq3 = fastdiv (sequence ,rq3_magic ); 43 44float * attn_data = dst ; 45 46// input state holds s0 only [S_v, S_v, H, n_seqs] — seq stride is D = H * S_v * S_v. 47// output state layout (per-slot D * n_seqs) — same per-(seq,head) offset as before. 48const int64_t state_in_offset = sequence * H * S_v * S_v + h_idx * S_v * S_v ; 49const int64_t state_out_offset = (sequence * H + h_idx )* S_v * S_v ; 50state += state_out_offset ; 51curr_state += state_in_offset + col * S_v ; 52attn_data += (sequence * n_tokens * H + h_idx )* S_v ; 53 54constexpr int warp_size = ggml_sycl_get_physical_warp_size ()< S_v ?ggml_sycl_get_physical_warp_size () :S_v ; 55 static_assert(S_v %warp_size == 0 ,"S_v must be a multiple of warp_size" ); 56constexpr int rows_per_lane = (S_v + warp_size - 1 ) /warp_size ; 57float s_shard [rows_per_lane ]; 58#pragma unroll 59for (int r = 0 ;r < rows_per_lane ;r ++ ) { 60const int i = r * warp_size + lane ; 61s_shard [r ]= curr_state [i ]; 62 } 63 64// snapshot slot mapping: slot 0 = most recent state, slot s = s tokens back. 65// When n_tokens < K only slots 0..n_tokens-1 are written; older slots are caller-owned. 66 67for (int t = 0 ;t < n_tokens ;t ++ ) { 68const float * q_t = q + iq3 * sq3 + t * sq2 + iq1 * sq1 ; 69const float * k_t = k + iq3 * sq3 + t * sq2 + iq1 * sq1 ; 70const float * v_t = v + sequence * sv3 + t * sv2 + h_idx * sv1 ; 71 72const int64_t gb_offset = sequence * sb3 + t * sb2 + h_idx * sb1 ; 73const float * beta_t = beta + gb_offset ; 74const float * g_t = g + gb_offset * (KDA ?S_v :1 ); 75 76const float beta_val = * beta_t ; 77 78if constexpr (!KDA ) { 79const float g_val = sycl::native::exp (* g_t ); 80 81// kv[col] = (S^T @ k)[col] = sum_i S[i][col] * k[i] 82float kv_shard = 0.0f ; 83#pragma unroll 84for (int r = 0 ;r < rows_per_lane ;r ++ ) { 85const int i = r * warp_size + lane ; 86kv_shard += s_shard [r ]* k_t [i ]; 87 } 88float kv_col = warp_reduce_sum < warp_size > (kv_shard ); 89 90// delta[col] = (v[col] - g * kv[col]) * beta 91float delta_col = (v_t [col ]- g_val * kv_col )* beta_val ; 92 93// fused: S[i][col] = g * S[i][col] + k[i] * delta[col] 94// attn[col] = (S^T @ q)[col] = sum_i S[i][col] * q[i] 95float attn_partial = 0.0f ; 96#pragma unroll 97for (int r = 0 ;r < rows_per_lane ;r ++ ) { 98const int i = r * warp_size + lane ; 99s_shard [r ]= g_val * s_shard [r ]+ k_t [i ]* delta_col ; 100attn_partial += s_shard [r ]* q_t [i ]; 101 } 102 103float attn_col = warp_reduce_sum < warp_size > (attn_partial ); 104 105if (lane == 0 ) { 106attn_data [col ]= attn_col * scale ; 107 } 108 }else { 109// kv[col] = sum_i g[i] * S[i][col] * k[i] 110float kv_shard = 0.0f ; 111#pragma unroll 112for (int r = 0 ;r < rows_per_lane ;r ++ ) { 113const int i = r * warp_size + lane ; 114kv_shard += sycl::native::exp (g_t [i ])* s_shard [r ]* k_t [i ]; 115 } 116 117float kv_col = warp_reduce_sum < warp_size > (kv_shard ); 118 119// delta[col] = (v[col] - kv[col]) * beta 120float delta_col = (v_t [col ]- kv_col )* beta_val ; 121 122// fused: S[i][col] = g[i] * S[i][col] + k[i] * delta[col] 123// attn[col] = (S^T @ q)[col] = sum_i S[i][col] * q[i] 124float attn_partial = 0.0f ; 125#pragma unroll 126for (int r = 0 ;r < rows_per_lane ;r ++ ) { 127const int i = r * warp_size + lane ; 128s_shard [r ]= sycl::native::exp (g_t [i ])* s_shard [r ]+ k_t [i ]* delta_col ; 129attn_partial += s_shard [r ]* q_t [i ]; 130 } 131 132float attn_col = warp_reduce_sum < warp_size > (attn_partial ); 133 134if (lane == 0 ) { 135attn_data [col ]= attn_col * scale ; 136 } 137 } 138 139attn_data += S_v * H ; 140 141 142// Write state back to global memory 143if constexpr (keep_rs_t ) { 144const int target_slot = (int )n_tokens - 1 - t ; 145if (target_slot >=0 && target_slot < K ) { 146float * curr_state = state + target_slot * state_slot_stride ; 147#pragma unroll 148for (int r = 0 ;r < rows_per_lane ;r ++ ) { 149const int i = r * warp_size + lane ; 150curr_state [col * S_v + i ]= s_shard [r ]; 151 } 152 } 153 } 154 } 155 156if constexpr (!keep_rs_t ) { 157#pragma unroll 158for (int r = 0 ;r < rows_per_lane ;r ++ ) { 159const int i = r * warp_size + lane ; 160state [col * S_v + i ]= s_shard [r ]; 161 } 162 } 163} 164 165template < bool KDA ,bool keep_rs_t > 166static void launch_gated_delta_net (const float * q_d , 167const float * k_d , 168const float * v_d , 169const float * g_d , 170const float * b_d , 171const float * s_d , 172float * dst_d , 173float * state_d , 174int64_t S_v , 175int64_t H , 176int64_t n_tokens , 177int64_t n_seqs , 178int64_t sq1 , 179int64_t sq2 , 180int64_t sq3 , 181int64_t sv1 , 182int64_t sv2 , 183int64_t sv3 , 184int64_t sb1 , 185int64_t sb2 , 186int64_t sb3 , 187int64_t neqk1 , 188int64_t rq3 , 189float scale , 190int64_t state_slot_stride , 191int K , 192 dpct::queue_ptr stream ) { 193//TODO: Add chunked kernel for even faster pre-fill 194const int warp_size = ggml_sycl_info ().devices [ggml_sycl_get_device ()].warp_size ; 195 196const int num_warps = 4 ; 197 dpct::dim3 grid_dims (H ,n_seqs , (S_v + num_warps - 1 ) /num_warps ); 198 dpct::dim3 block_dims (warp_size <=S_v ?warp_size :S_v ,num_warps ,1 ); 199 200const sycl::uint3 neqk1_magic = init_fastdiv_values (neqk1 ); 201const sycl::uint3 rq3_magic = init_fastdiv_values (rq3 ); 202 203switch (S_v ) { 204case 16 : 205 { 206constexpr int sv = 16 ; 207stream -> parallel_for (sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 208 [= ](sycl::nd_item < 3 > /*item_ct1*/ ) [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 209gated_delta_net_sycl < sv ,KDA ,keep_rs_t > (q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d ,H ,n_tokens , 210sq1 ,sq2 ,sq3 ,sv1 ,sv2 ,sv3 ,sb1 ,sb2 , 211sb3 ,neqk1_magic ,rq3_magic ,scale ,state_slot_stride ,K ); 212 }); 213 } 214break ; 215case 32 : 216 { 217constexpr int sv = 32 ; 218stream -> parallel_for (sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 219 [= ](sycl::nd_item < 3 > /*item_ct1*/ ) [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 220gated_delta_net_sycl < sv ,KDA ,keep_rs_t > (q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d ,H ,n_tokens , 221sq1 ,sq2 ,sq3 ,sv1 ,sv2 ,sv3 ,sb1 ,sb2 , 222sb3 ,neqk1_magic ,rq3_magic ,scale ,state_slot_stride ,K ); 223 }); 224 } 225break ; 226case 64 : { 227 { 228constexpr int sv = 64 ; 229stream -> parallel_for (sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 230 [= ](sycl::nd_item < 3 > /*item_ct1*/ ) [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 231gated_delta_net_sycl < sv ,KDA ,keep_rs_t > ( 232q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d ,H ,n_tokens ,sq1 ,sq2 , 233sq3 ,sv1 ,sv2 ,sv3 ,sb1 ,sb2 ,sb3 ,neqk1_magic ,rq3_magic ,scale ,state_slot_stride ,K ); 234 }); 235 } 236break ; 237 } 238case 128 : { 239 { 240constexpr int sv = 128 ; 241stream -> parallel_for (sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 242 [= ](sycl::nd_item < 3 > /*item_ct1*/ ) [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 243gated_delta_net_sycl < sv ,KDA ,keep_rs_t > ( 244q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d ,H ,n_tokens ,sq1 ,sq2 , 245sq3 ,sv1 ,sv2 ,sv3 ,sb1 ,sb2 ,sb3 ,neqk1_magic ,rq3_magic ,scale ,state_slot_stride ,K ); 246 }); 247 } 248break ; 249 } 250default : 251GGML_ABORT ("fatal error" ); 252break ; 253 } 254} 255 256static void ggml_sycl_op_gated_delta_net_impl (ggml_backend_sycl_context & ctx ,ggml_tensor * dst , 257const ggml_sycl_gated_delta_net_fused_cache * cache ) { 258ggml_tensor * src_q = dst -> src [0 ]; 259ggml_tensor * src_k = dst -> src [1 ]; 260ggml_tensor * src_v = dst -> src [2 ]; 261ggml_tensor * src_g = dst -> src [3 ]; 262ggml_tensor * src_beta = dst -> src [4 ]; 263ggml_tensor * src_state = dst -> src [5 ]; 264 265GGML_TENSOR_LOCALS (int64_t ,neq ,src_q ,ne ); 266GGML_TENSOR_LOCALS (size_t ,nbq ,src_q ,nb ); 267GGML_TENSOR_LOCALS (int64_t ,nek ,src_k ,ne ); 268GGML_TENSOR_LOCALS (size_t ,nbk ,src_k ,nb ); 269GGML_TENSOR_LOCALS (int64_t ,nev ,src_v ,ne ); 270GGML_TENSOR_LOCALS (size_t ,nbv ,src_v ,nb ); 271GGML_TENSOR_LOCALS (size_t ,nbb ,src_beta ,nb ); 272 273const int64_t S_v = nev0 ; 274const int64_t H = nev1 ; 275const int64_t n_tokens = nev2 ; 276const int64_t n_seqs = nev3 ; 277 278const bool kda = (src_g -> ne [0 ]== S_v ); 279 280GGML_ASSERT (neq1 == nek1 ); 281const int64_t neqk1 = neq1 ; 282 283const int64_t rq3 = nev3 /neq3 ; 284 285const float * q_d = (const float * )src_q -> data ; 286const float * k_d = (const float * )src_k -> data ; 287const float * v_d = (const float * )src_v -> data ; 288const float * g_d = (const float * )src_g -> data ; 289const float * b_d = (const float * )src_beta -> data ; 290 291const float * s_d = (const float * )src_state -> data ; 292float * dst_d = (float * )dst -> data ; 293 294GGML_ASSERT (ggml_is_contiguous_rows (src_q )); 295GGML_ASSERT (ggml_is_contiguous_rows (src_k )); 296GGML_ASSERT (ggml_is_contiguous_rows (src_v )); 297GGML_ASSERT (ggml_are_same_stride (src_q ,src_k )); 298GGML_ASSERT (src_g -> ne [0 ]== 1 || kda ); 299GGML_ASSERT (ggml_is_contiguous (src_g )); 300GGML_ASSERT (ggml_is_contiguous (src_beta )); 301GGML_ASSERT (ggml_is_contiguous (src_state )); 302 303// strides in floats (beta strides used for both g and beta offset computation) 304const int64_t sq1 = nbq1 /sizeof (float ); 305const int64_t sq2 = nbq2 /sizeof (float ); 306const int64_t sq3 = nbq3 /sizeof (float ); 307const int64_t sv1 = nbv1 /sizeof (float ); 308const int64_t sv2 = nbv2 /sizeof (float ); 309const int64_t sv3 = nbv3 /sizeof (float ); 310const int64_t sb1 = nbb1 /sizeof (float ); 311const int64_t sb2 = nbb2 /sizeof (float ); 312const int64_t sb3 = nbb3 /sizeof (float ); 313 314const float scale = 1.0f /sqrtf ((float )S_v ); 315 316 dpct::queue_ptr stream = ctx .stream (); 317 318// K (snapshot slot count) is an op param; state holds s0 only [S_v, S_v, H, n_seqs]. 319const int K = ggml_get_op_params_i32 (dst ,0 ); 320const bool keep_rs = K > 1 ; 321 322// recurrent state -> dst tail (after attention scores), or the cache when fusing 323float * state_d = dst_d + S_v * H * n_tokens * n_seqs ; 324int64_t state_slot_stride = S_v * S_v * H * n_seqs ; 325if (cache != nullptr ) { 326state_d = cache -> data ; 327state_slot_stride = cache -> slot_stride ; 328 } 329 330if (kda ) { 331if (keep_rs ) { 332launch_gated_delta_net < true, true> (q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d , 333S_v ,H ,n_tokens ,n_seqs ,sq1 ,sq2 ,sq3 ,sv1 ,sv2 ,sv3 , 334sb1 ,sb2 ,sb3 ,neqk1 ,rq3 ,scale ,state_slot_stride ,K ,stream ); 335 }else { 336launch_gated_delta_net < true, false> (q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d , 337S_v ,H ,n_tokens ,n_seqs ,sq1 ,sq2 ,sq3 ,sv1 ,sv2 ,sv3 , 338sb1 ,sb2 ,sb3 ,neqk1 ,rq3 ,scale ,state_slot_stride ,K ,stream ); 339 } 340 }else { 341if (keep_rs ) { 342launch_gated_delta_net < false, true> (q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d , 343S_v ,H ,n_tokens ,n_seqs ,sq1 ,sq2 ,sq3 ,sv1 ,sv2 ,sv3 , 344sb1 ,sb2 ,sb3 ,neqk1 ,rq3 ,scale ,state_slot_stride ,K ,stream ); 345 }else { 346launch_gated_delta_net < false, false> (q_d ,k_d ,v_d ,g_d ,b_d ,s_d ,dst_d ,state_d , 347S_v ,H ,n_tokens ,n_seqs ,sq1 ,sq2 ,sq3 ,sv1 ,sv2 ,sv3 , 348sb1 ,sb2 ,sb3 ,neqk1 ,rq3 ,scale ,state_slot_stride ,K ,stream ); 349 } 350 } 351} 352 353void ggml_sycl_op_gated_delta_net (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 354ggml_sycl_op_gated_delta_net_impl (ctx ,dst ,nullptr ); 355} 356 357void ggml_sycl_gated_delta_net (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 358scope_op_debug_print scope_dbg_print (__func__ ,dst ,/*num_src=*/ 6 ); 359ggml_sycl_op_gated_delta_net (ctx ,dst ); 360} 361 362void ggml_sycl_op_gated_delta_net_fused_cache (ggml_backend_sycl_context & ctx ,ggml_tensor * dst , 363ggml_sycl_gated_delta_net_fused_cache cache ) { 364scope_op_debug_print scope_dbg_print (__func__ ,dst ,/*num_src=*/ 6 ); 365ggml_sycl_op_gated_delta_net_impl (ctx ,dst ,& cache ); 366}