char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
bf38346d1
char/aliceai-t5-moe
1#include <sycl/sycl.hpp> 2#include "wkv.hpp" 3 4constexpr int WKV_BLOCK_SIZE = 64 ; 5 6// Helper function for the main kernel 7template < int block_size > 8static void rwkv_wkv6_f32_kernel ( 9const int B ,const int T ,const int C ,const int H , 10const float * k ,const float * v ,const float * r , 11const float * tf ,const float * td ,const float * s , 12float * dst ,const sycl::nd_item < 3 >& item_ct1 ,float * shared_mem ) { 13 14const int tid = item_ct1 .get_local_id (2 ); 15const int bid = item_ct1 .get_group (2 ); 16 17const int head_size = block_size ; 18const int batch_i = bid /H ; 19const int head_i = bid %H ; 20const int state_size = C * head_size ; 21const int n_seq_tokens = T /B ; 22 23// Set up shared memory pointers 24float * _k = shared_mem ; 25float * _r = _k + head_size ; 26float * _tf = _r + head_size ; 27float * _td = _tf + head_size ; 28 29// Local state array 30float state [block_size ]; 31 32// Load initial state 33#pragma unroll 34for (int i = 0 ;i < head_size ;i ++ ) { 35state [i ]= s [batch_i * state_size + head_i * head_size * head_size + i * head_size + tid ]; 36 } 37 38// Sync threads before shared memory operations 39item_ct1 .barrier (sycl::access::fence_space::local_space ); 40 41// Load time-mixing parameters 42_tf [tid ]= tf [head_i * head_size + tid ]; 43item_ct1 .barrier (sycl::access::fence_space::local_space ); 44 45// Main sequence processing loop 46for (int t = batch_i * n_seq_tokens * C + head_i * head_size + tid ; 47t < (batch_i + 1 )* n_seq_tokens * C + head_i * head_size + tid ; 48t += C ) { 49 50item_ct1 .barrier (sycl::access::fence_space::local_space ); 51 52// Load current timestep data to shared memory 53_k [tid ]= k [t ]; 54_r [tid ]= r [t ]; 55_td [tid ]= td [t ]; 56 57item_ct1 .barrier (sycl::access::fence_space::local_space ); 58 59const float _v = v [t ]; 60float y = 0 ; 61 62// Process in chunks of 4 for better vectorization 63 sycl::float4 k4 ,r4 ,tf4 ,td4 ,s4 ; 64#pragma unroll 65for (int j = 0 ;j < head_size ;j += 4 ) { 66// Load data in vec4 chunks 67k4 = sycl::float4 (_k [j ],_k [j + 1 ],_k [j + 2 ],_k [j + 3 ]); 68r4 = sycl::float4 (_r [j ],_r [j + 1 ],_r [j + 2 ],_r [j + 3 ]); 69tf4 = sycl::float4 (_tf [j ],_tf [j + 1 ],_tf [j + 2 ],_tf [j + 3 ]); 70td4 = sycl::float4 (_td [j ],_td [j + 1 ],_td [j + 2 ],_td [j + 3 ]); 71s4 = sycl::float4 (state [j ],state [j + 1 ],state [j + 2 ],state [j + 3 ]); 72 73// Compute key-value product 74 sycl::float4 kv4 = k4 * _v ; 75 76// Accumulate weighted sum 77y += sycl::dot (r4 ,tf4 * kv4 + s4 ); 78 79// Update state 80s4 = s4 * td4 + kv4 ; 81 82// Store updated state 83state [j ]= s4 .x (); 84state [j + 1 ]= s4 .y (); 85state [j + 2 ]= s4 .z (); 86state [j + 3 ]= s4 .w (); 87 } 88 89dst [t ]= y ; 90 } 91 92// Save final state 93#pragma unroll 94for (int i = 0 ;i < head_size ;i ++ ) { 95dst [T * C + batch_i * state_size + head_i * head_size * head_size + i * head_size + tid ]= state [i ]; 96 } 97} 98 99template < int block_size > 100static void rwkv_wkv7_f32_kernel ( 101const int B ,const int T ,const int C ,const int H , 102const float * r ,const float * w ,const float * k ,const float * v , 103const float * a ,const float * b ,const float * s , 104float * dst ,const sycl::nd_item < 3 >& item_ct1 ,float * shared_mem ) { 105 106const int tid = item_ct1 .get_local_id (2 ); 107const int bid = item_ct1 .get_group (2 ); 108 109const int head_size = block_size ; 110const int batch_i = bid /H ; 111const int head_i = bid %H ; 112const int state_size = C * head_size ; 113const int n_seq_tokens = T /B ; 114 115float * _r = shared_mem ; 116float * _w = _r + head_size ; 117float * _k = _w + head_size ; 118float * _a = _k + head_size ; 119float * _b = _a + head_size ; 120 121float state [block_size ]; 122 123#pragma unroll 124for (int i = 0 ;i < head_size ;i ++ ) { 125state [i ]= s [batch_i * state_size + head_i * head_size * head_size + tid * head_size + i ]; 126 } 127 128for (int t = batch_i * n_seq_tokens * C + head_i * head_size + tid ; 129t < (batch_i + 1 )* n_seq_tokens * C + head_i * head_size + tid ; 130t += C ) { 131 132item_ct1 .barrier (sycl::access::fence_space::local_space ); 133 134_r [tid ]= r [t ]; 135_w [tid ]= w [t ]; 136_k [tid ]= k [t ]; 137_a [tid ]= a [t ]; 138_b [tid ]= b [t ]; 139 140item_ct1 .barrier (sycl::access::fence_space::local_space ); 141 142const float _v = v [t ]; 143float y = 0 ,sa = 0 ; 144 sycl::float4 a4 ,s4 ; 145 146#pragma unroll 147for (int j = 0 ;j < head_size ;j += 4 ) { 148a4 = sycl::float4 (_a [j ],_a [j + 1 ],_a [j + 2 ],_a [j + 3 ]); 149s4 = sycl::float4 (state [j ],state [j + 1 ],state [j + 2 ],state [j + 3 ]); 150sa += sycl::dot (a4 ,s4 ); 151 } 152 153 sycl::float4 r4 ,w4 ,k4 ,b4 ; 154#pragma unroll 155for (int j = 0 ;j < head_size ;j += 4 ) { 156r4 = sycl::float4 (_r [j ],_r [j + 1 ],_r [j + 2 ],_r [j + 3 ]); 157w4 = sycl::float4 (_w [j ],_w [j + 1 ],_w [j + 2 ],_w [j + 3 ]); 158k4 = sycl::float4 (_k [j ],_k [j + 1 ],_k [j + 2 ],_k [j + 3 ]); 159b4 = sycl::float4 (_b [j ],_b [j + 1 ],_b [j + 2 ],_b [j + 3 ]); 160s4 = sycl::float4 (state [j ],state [j + 1 ],state [j + 2 ],state [j + 3 ]); 161 162 sycl::float4 kv4 = k4 * _v ; 163 164s4 = s4 * w4 + kv4 + sa * b4 ; 165y += sycl::dot (r4 ,s4 ); 166 167state [j ]= s4 .x (); 168state [j + 1 ]= s4 .y (); 169state [j + 2 ]= s4 .z (); 170state [j + 3 ]= s4 .w (); 171 } 172 173dst [t ]= y ; 174 } 175 176#pragma unroll 177for (int i = 0 ;i < head_size ;i ++ ) { 178dst [T * C + batch_i * state_size + head_i * head_size * head_size + tid * head_size + i ]= state [i ]; 179 } 180} 181 182void ggml_sycl_op_rwkv_wkv6 (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 183scope_op_debug_print scope_dbg_print (__func__ ,dst ,/*num_src=*/ 6 ); 184const float * k_d = (const float * )dst -> src [0 ]-> data ; 185const float * v_d = (const float * )dst -> src [1 ]-> data ; 186const float * r_d = (const float * )dst -> src [2 ]-> data ; 187const float * tf_d = (const float * )dst -> src [3 ]-> data ; 188const float * td_d = (const float * )dst -> src [4 ]-> data ; 189const float * s_d = (const float * )dst -> src [5 ]-> data ; 190float * dst_d = (float * )dst -> data ; 191 192const int64_t B = dst -> src [5 ]-> ne [1 ]; 193const int64_t T = dst -> src [0 ]-> ne [2 ]; 194const int64_t C = dst -> ne [0 ]; 195const int64_t H = dst -> src [0 ]-> ne [1 ]; 196 197GGML_ASSERT (dst -> src [5 ]-> type == GGML_TYPE_F32 ); 198GGML_ASSERT (C %H == 0 ); 199GGML_ASSERT (C /H == WKV_BLOCK_SIZE || C /H == WKV_BLOCK_SIZE * 2 );// The current sycl kernel is designed for RWKV6, HEAD_SIZE == 64 200 201 dpct::queue_ptr stream = ctx .stream (); 202 203// Calculate execution configuration 204const size_t shared_mem_size = C /H * 4 * sizeof (float );// For k, r, tf, td 205 sycl::range < 3 > block_dims (1 ,1 ,C /H ); 206 sycl::range < 3 > grid_dims (1 ,1 ,B * H ); 207 208// Submit kernel 209if (C /H == WKV_BLOCK_SIZE ) { 210stream -> submit ([& ](sycl::handler & cgh ) { 211 sycl::local_accessor < float ,1 > shared_mem_acc (shared_mem_size ,cgh ); 212 213cgh .parallel_for ( 214 sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 215 [= ](sycl::nd_item < 3 > item_ct1 ) { 216rwkv_wkv6_f32_kernel < WKV_BLOCK_SIZE > ( 217B ,T ,C ,H ,k_d ,v_d ,r_d ,tf_d ,td_d ,s_d ,dst_d , 218item_ct1 , (float * )shared_mem_acc .get_multi_ptr < sycl::access::decorated::no > ().get () 219 ); 220 }); 221 }); 222 }else { 223stream -> submit ([& ](sycl::handler & cgh ) { 224 sycl::local_accessor < float ,1 > shared_mem_acc (shared_mem_size ,cgh ); 225 226cgh .parallel_for ( 227 sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 228 [= ](sycl::nd_item < 3 > item_ct1 ) { 229rwkv_wkv6_f32_kernel < WKV_BLOCK_SIZE * 2 > ( 230B ,T ,C ,H ,k_d ,v_d ,r_d ,tf_d ,td_d ,s_d ,dst_d , 231item_ct1 , (float * )shared_mem_acc .get_multi_ptr < sycl::access::decorated::no > ().get () 232 ); 233 }); 234 }); 235 } 236} 237 238void ggml_sycl_op_rwkv_wkv7 (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 239scope_op_debug_print scope_dbg_print (__func__ ,dst ,/*num_src=*/ 7 ); 240const float * r_d = (const float * )dst -> src [0 ]-> data ; 241const float * w_d = (const float * )dst -> src [1 ]-> data ; 242const float * k_d = (const float * )dst -> src [2 ]-> data ; 243const float * v_d = (const float * )dst -> src [3 ]-> data ; 244const float * a_d = (const float * )dst -> src [4 ]-> data ; 245const float * b_d = (const float * )dst -> src [5 ]-> data ; 246const float * s_d = (const float * )dst -> src [6 ]-> data ; 247float * dst_d = (float * )dst -> data ; 248 249const int64_t B = dst -> src [6 ]-> ne [1 ]; 250const int64_t T = dst -> src [0 ]-> ne [2 ]; 251const int64_t C = dst -> ne [0 ]; 252const int64_t H = dst -> src [0 ]-> ne [1 ]; 253 254GGML_ASSERT (dst -> src [6 ]-> type == GGML_TYPE_F32 ); 255GGML_ASSERT (C %H == 0 ); 256GGML_ASSERT (C /H == WKV_BLOCK_SIZE || C /H == WKV_BLOCK_SIZE * 2 ); 257 258 dpct::queue_ptr stream = ctx .stream (); 259 260// Calculate execution configuration 261const size_t shared_mem_size = C /H * 5 * sizeof (float );// For r, w, k, a, b 262 sycl::range < 3 > block_dims (1 ,1 ,C /H ); 263 sycl::range < 3 > grid_dims (1 ,1 ,B * H ); 264 265// Submit kernel 266if (C /H == WKV_BLOCK_SIZE ) { 267stream -> submit ([& ](sycl::handler & cgh ) { 268 sycl::local_accessor < float ,1 > shared_mem_acc (shared_mem_size ,cgh ); 269 270cgh .parallel_for ( 271 sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 272 [= ](sycl::nd_item < 3 > item_ct1 ) { 273rwkv_wkv7_f32_kernel < WKV_BLOCK_SIZE > ( 274B ,T ,C ,H ,r_d ,w_d ,k_d ,v_d ,a_d ,b_d ,s_d ,dst_d , 275item_ct1 , (float * )shared_mem_acc .get_multi_ptr < sycl::access::decorated::no > ().get () 276 ); 277 }); 278 }); 279 }else { 280stream -> submit ([& ](sycl::handler & cgh ) { 281 sycl::local_accessor < float ,1 > shared_mem_acc (shared_mem_size ,cgh ); 282 283cgh .parallel_for ( 284 sycl::nd_range < 3 > (grid_dims * block_dims ,block_dims ), 285 [= ](sycl::nd_item < 3 > item_ct1 ) { 286rwkv_wkv7_f32_kernel < WKV_BLOCK_SIZE * 2 > ( 287B ,T ,C ,H ,r_d ,w_d ,k_d ,v_d ,a_d ,b_d ,s_d ,dst_d , 288item_ct1 , (float * )shared_mem_acc .get_multi_ptr < sycl::access::decorated::no > ().get () 289 ); 290 }); 291 }); 292 } 293}