char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
e7e3f3509
char/aliceai-t5-moe
1#include "softmax.hpp" 2#include <cstdint> 3#include <utility> 4#include <cmath> 5 6 7template < typename T > static __dpct_inline__ float t2f32 (T val ) { 8return (float )val ; 9} 10 11template <> float __dpct_inline__ t2f32 < sycl::half > (sycl::half val ) { 12return sycl::vec < sycl::half ,1 > (val ) 13 .convert < float , sycl::rounding_mode::automatic > ()[0 ]; 14} 15 16struct soft_max_params { 17 18int64_t nheads ; 19uint32_t n_head_log2 ; 20int64_t ncols ; 21int64_t nrows_x ; 22int64_t nrows_y ; 23int64_t ne00 ; 24int64_t ne01 ; 25int64_t ne02 ; 26int64_t ne03 ; 27int64_t nb11 ; 28int64_t nb12 ; 29int64_t nb13 ; 30 31int64_t ne12 ; 32int64_t ne13 ; 33float scale ; 34float max_bias ; 35float m0 ; 36float m1 ; 37}; 38 39// When ncols_template == 0 the bounds for the loops in this function are not known and can't be unrolled. 40// As we want to keep pragma unroll for all other cases we suppress the clang transformation warning here. 41#ifdef __clang__ 42#pragma clang diagnostic push 43#pragma clang diagnostic ignored "-Wpass-failed" 44#endif // __clang__ 45template < bool use_shared ,int ncols_template ,int block_size_template ,typename T > 46static void soft_max_f32 (const float * x , 47const T * mask , 48const float * sinks , 49float * dst , 50const soft_max_params p , 51uint8_t * dpct_local ) { 52auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 53const int ncols = ncols_template == 0 ?p .ncols :ncols_template ; 54const int block_size = block_size_template == 0 55 ?item_ct1 .get_local_range (2 ) 56 :block_size_template ; 57const int nthreads = block_size ; 58const int nwarps = nthreads /WARP_SIZE ; 59const size_t nreduce = nwarps /WARP_SIZE ; 60 61const int tid = item_ct1 .get_local_id (2 ); 62 63const int64_t i03 = item_ct1 .get_group (0 ); 64const int64_t i02 = item_ct1 .get_group (1 ); 65const int64_t i01 = item_ct1 .get_group (2 ); 66 67//TODO: noncontigous inputs/outputs 68const int rowx = item_ct1 .get_group (2 )+ 69item_ct1 .get_group (1 )* item_ct1 .get_group_range (2 )+ 70item_ct1 .get_group (0 )* item_ct1 .get_group_range (2 )* 71item_ct1 .get_group_range (1 ); 72 73const int64_t i11 = i01 ; 74const int64_t i12 = i02 %p .ne12 ; 75const int64_t i13 = i03 %p .ne13 ; 76 77x += int64_t (rowx )* ncols ; 78mask += (i11 * p .nb11 + i12 * p .nb12 + i13 * p .nb13 ) /sizeof (T )* (mask != nullptr ); 79dst += int64_t (rowx )* ncols ; 80 81const int warp_id = item_ct1 .get_local_id (2 ) /WARP_SIZE ; 82const int lane_id = item_ct1 .get_local_id (2 ) %WARP_SIZE ; 83 84const float slope = get_alibi_slope (p .max_bias ,i02 ,p .n_head_log2 ,p .m0 ,p .m1 ); 85 86float * buf_iw = (float * )dpct_local ; 87 88// shared memory buffer to cache values between iterations: 89float * vals = use_shared ?buf_iw + sycl::max (nwarps ,WARP_SIZE ) :dst ; 90float max_val = sinks ?sinks [i02 ] :- INFINITY ; 91#pragma unroll 92for (int col0 = 0 ;col0 < ncols ;col0 += block_size ) { 93const int col = col0 + tid ; 94 95if (ncols_template == 0 && col >=ncols ) { 96break ; 97 } 98 99const float val = x [col ]* p .scale + (mask ?slope * t2f32 (mask [col ]) :0.0f ); 100 101vals [col ]= val ; 102max_val = sycl::max (max_val ,val ); 103 } 104// find the max value in the block 105max_val = warp_reduce_max < WARP_SIZE > (max_val ); 106 107if (block_size > WARP_SIZE ) { 108if (lane_id == 0 ) { 109buf_iw [warp_id ]= max_val ; 110 } 111item_ct1 .barrier (); 112 113max_val = - INFINITY ; 114for (int i = lane_id ;i < nwarps ;i += WARP_SIZE ) { 115max_val = sycl::max (max_val ,buf_iw [i ]); 116 } 117max_val = warp_reduce_max < WARP_SIZE > (max_val ); 118 } 119float tmp = 0.0f ;// partial sum 120 121#pragma unroll 122for (int col0 = 0 ;col0 < ncols ;col0 += block_size ) { 123const int col = col0 + tid ; 124 125if (ncols_template == 0 && col >=ncols ) { 126break ; 127 } 128 129const float val = sycl::native::exp (sycl::max (vals [col ]- max_val ,-80.0f )); 130tmp += val ; 131vals [col ]= val ; 132 } 133// find the sum of exps in the block 134tmp = warp_reduce_sum < WARP_SIZE > (tmp ); 135if (block_size > WARP_SIZE ) { 136item_ct1 .barrier (); 137if (warp_id == 0 ) { 138buf_iw [lane_id ]= 0.0f ; 139for (size_t i = 1 ;i < nreduce ;i += 1 ) { 140buf_iw [lane_id + i * WARP_SIZE ]= 0.f ; 141 } 142 } 143item_ct1 .barrier (); 144 145if (lane_id == 0 ) { 146buf_iw [warp_id ]= tmp ; 147 } 148item_ct1 .barrier (); 149 150tmp = buf_iw [lane_id ]; 151for (size_t i = 1 ;i < nreduce ;i += 1 ) { 152tmp += buf_iw [lane_id + i * WARP_SIZE ]; 153 } 154tmp = warp_reduce_sum < WARP_SIZE > (tmp ); 155 } 156if (sinks ) { 157tmp += sycl::native::exp (sycl::max (sinks [i02 ]- max_val ,-80.0f )); 158 } 159const float inv_sum = 1.0f /tmp ; 160 161#pragma unroll 162for (int col0 = 0 ;col0 < ncols ;col0 += block_size ) { 163const int col = col0 + tid ; 164 165if (ncols_template == 0 && col >=ncols ) { 166return ; 167 } 168 169dst [col ]= vals [col ]* inv_sum ; 170 } 171} 172#ifdef __clang__ 173#pragma clang diagnostic pop 174#endif // __clang__ 175 176static void soft_max_back_f32 (const float * grad ,const float * dstf ,float * dst , 177const int ncols ,const float scale ) { 178auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item < 3 > (); 179const int tid = item_ct1 .get_local_id (2 ); 180const int rowx = item_ct1 .get_group (2 ); 181 182grad += int64_t (rowx )* ncols ; 183dstf += int64_t (rowx )* ncols ; 184dst += int64_t (rowx )* ncols ; 185 186float dgf_dot = 0.0f ;// dot product of dst from forward pass and gradients 187 188for (int col = tid ;col < ncols ;col += WARP_SIZE ) { 189dgf_dot += dstf [col ]* grad [col ]; 190 } 191 192dgf_dot = warp_reduce_sum < WARP_SIZE > (dgf_dot ); 193 194for (int col = tid ;col < ncols ;col += WARP_SIZE ) { 195dst [col ]= scale * (grad [col ]- dgf_dot )* dstf [col ]; 196 } 197} 198 199template < int ...Ns ,typename T > 200static void launch_soft_max_kernels (const float * x , 201const T * mask , 202const float * sinks , 203float * dst , 204const soft_max_params & p , 205 dpct::queue_ptr stream , 206 dpct::dim3 block_dims , 207 dpct::dim3 block_nums , 208size_t nbytes_shared ) 209{ 210auto launch_kernel = [= ](auto I )-> bool { 211constexpr int ncols = decltype(I )::value ; 212constexpr int block = (ncols > 1024 ?1024 :ncols ); 213if (p .ncols == ncols ) { 214stream -> submit ([& ](sycl::handler & cgh ) { 215 sycl::local_accessor < uint8_t ,1 > dpct_local_acc_ct1 ( 216 sycl::range < 1 > (nbytes_shared ),cgh ); 217 218cgh .parallel_for ( 219 sycl::nd_range < 3 > (block_nums * block_dims ,block_dims ), 220 [= ](sycl::nd_item < 3 > item_ct1 ) [[sycl ::reqd_sub_group_size ( 221WARP_SIZE )]] { 222soft_max_f32 < true,ncols ,block > ( 223x ,mask ,sinks ,dst ,p , 224dpct_local_acc_ct1 225 .get_multi_ptr < sycl::access::decorated::no > () 226 .get ()); 227GGML_UNUSED (item_ct1 ); 228 }); 229 }); 230return true; 231 } 232return false; 233 }; 234 235// unary fold over launch_kernel 236if ((launch_kernel (std::integral_constant < int ,Ns > {})|| ...)) { 237return ; 238 } 239 240stream -> submit ([& ](sycl::handler & cgh ) { 241 sycl::local_accessor < uint8_t ,1 > dpct_local_acc_ct1 ( 242 sycl::range < 1 > (nbytes_shared ),cgh ); 243 244cgh .parallel_for ( 245 sycl::nd_range < 3 > (block_nums * block_dims ,block_dims ), 246 [= ](sycl::nd_item < 3 > item_ct1 ) 247 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 248soft_max_f32 < true,0 ,0 > ( 249x ,mask ,sinks ,dst ,p , 250dpct_local_acc_ct1 251 .get_multi_ptr < sycl::access::decorated::no > () 252 .get ()); 253GGML_UNUSED (item_ct1 ); 254 }); 255 }); 256} 257 258template < typename T > 259static void soft_max_f32_sycl (const float * x ,const T * mask , 260const float * sinks ,float * dst , 261const soft_max_params & params , 262 dpct::queue_ptr stream ,int device ) { 263int nth = WARP_SIZE ; 264int max_block_size = ggml_sycl_info ().max_work_group_sizes [device ]; 265const int64_t ncols_x = params .ncols ; 266 267while (nth < ncols_x && nth < max_block_size )nth *=2 ; 268if (nth > max_block_size )nth = max_block_size ; 269 270const dpct::dim3 block_dims (nth ,1 ,1 ); 271const dpct::dim3 block_nums (params .ne01 ,params .ne02 ,params .ne03 ); 272const size_t nbytes_shared = 273 (GGML_PAD (ncols_x ,WARP_SIZE )+ WARP_SIZE )* sizeof (float ); 274 275const int id = get_current_device_id (); 276const size_t smpbo = ggml_sycl_info ().devices [id ].smpbo ; 277 278if (nbytes_shared <=smpbo && ncols_x <=max_block_size ) { 279launch_soft_max_kernels < 32 ,64 ,128 ,256 ,512 ,1024 ,2048 ,4096 > ( 280x ,mask ,sinks ,dst ,params ,stream ,block_dims ,block_nums , 281nbytes_shared ); 282 }else { 283const size_t nbytes_shared_low = WARP_SIZE * sizeof (float ); 284 285stream -> submit ([& ](sycl::handler & cgh ) { 286 sycl::local_accessor < uint8_t ,1 > dpct_local_acc_ct1 ( 287 sycl::range < 1 > (nbytes_shared_low ),cgh ); 288 289cgh .parallel_for ( 290 sycl::nd_range < 3 > (block_nums * block_dims ,block_dims ), 291 [= ](sycl::nd_item < 3 > item_ct1 ) 292 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 293soft_max_f32 < false,0 ,0 > ( 294x ,mask ,sinks ,dst ,params , 295dpct_local_acc_ct1 296 .get_multi_ptr < sycl::access::decorated::no > () 297 .get ()); 298GGML_UNUSED (item_ct1 ); 299 }); 300 }); 301 } 302} 303 304static void soft_max_back_f32_sycl (const float * grad , 305const float * dstf , 306float * dst , 307const int ncols , 308const int nrows , 309const float scale , 310 dpct::queue_ptr stream ) { 311const dpct::dim3 block_dims (WARP_SIZE ,1 ,1 ); 312const dpct::dim3 block_nums (nrows ,1 ,1 ); 313 314stream -> parallel_for (sycl::nd_range < 3 > (block_nums * block_dims ,block_dims ), 315 [= ](sycl::nd_item < 3 > item_ct1 ) { 316soft_max_back_f32 (grad ,dstf ,dst ,ncols ,scale ); 317GGML_UNUSED (item_ct1 ); 318 }); 319} 320 321void ggml_sycl_op_soft_max (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 322scope_op_debug_print scope_dbg_print (__func__ ,dst ,/*num_src=*/ 2 ); 323 324const ggml_tensor * src0 = dst -> src [0 ]; 325const ggml_tensor * src1 = dst -> src [1 ]; 326const ggml_tensor * src2 = dst -> src [2 ]; 327 328const float * src0_d = (const float * )src0 -> data ; 329const void * src1_d = src1 ? (const void * )src1 -> data :nullptr ; 330const void * src2_d = src2 ? (const void * )src2 -> data :nullptr ; 331float * dst_d = (float * )dst -> data ; 332 333 dpct::queue_ptr stream = ctx .stream (); 334 335GGML_ASSERT (src0 -> type == GGML_TYPE_F32 ); 336GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 337 338// src1 contains mask and it is optional 339GGML_ASSERT (!src1 || src1 -> type == GGML_TYPE_F16 || src1 -> type == GGML_TYPE_F32 ); 340 341const int64_t nrows_x = ggml_nrows (src0 ); 342const int64_t nrows_y = src0 -> ne [1 ]; 343 344const int64_t ne00 = src0 -> ne [0 ]; 345 346float scale = 1.0f ; 347float max_bias = 0.0f ; 348 349memcpy (& scale , (const float * )dst -> op_params + 0 ,sizeof (float )); 350memcpy (& max_bias , (const float * )dst -> op_params + 1 ,sizeof (float )); 351 352const bool use_f16 = (src1 && src1 -> type == GGML_TYPE_F16 ); 353 354const int64_t nb11 = src1 ?src1 -> nb [1 ] :1 ; 355const int64_t nb12 = src1 ?src1 -> nb [2 ] :1 ; 356const int64_t nb13 = src1 ?src1 -> nb [3 ] :1 ; 357 358const int64_t ne12 = src1 ?src1 -> ne [2 ] :1 ; 359const int64_t ne13 = src1 ?src1 -> ne [3 ] :1 ; 360 361const uint32_t n_head = src0 -> ne [2 ]; 362const uint32_t n_head_log2 = 1u << (uint32_t )floorf (log2f ((float )n_head )); 363 364const float m0 = powf (2.0f ,- (max_bias ) /n_head_log2 ); 365const float m1 = powf (2.0f ,- (max_bias /2.0f ) /n_head_log2 ); 366 367 368soft_max_params params = {}; 369params .nheads = src0 -> ne [2 ]; 370params .n_head_log2 = n_head_log2 ; 371params .ncols = ne00 ; 372params .nrows_x = nrows_x ; 373params .nrows_y = nrows_y ; 374params .ne00 = src0 -> ne [0 ]; 375params .ne01 = src0 -> ne [1 ]; 376params .ne02 = src0 -> ne [2 ]; 377params .ne03 = src0 -> ne [3 ]; 378params .nb11 = nb11 ; 379params .nb12 = nb12 ; 380params .nb13 = nb13 ; 381params .ne12 = ne12 ; 382params .ne13 = ne13 ; 383params .scale = scale ; 384params .max_bias = max_bias ; 385params .m0 = m0 ; 386params .m1 = m1 ; 387 388if (use_f16 ) { 389soft_max_f32_sycl (src0_d , (const sycl::half * )src1_d , 390 (const float * )src2_d ,dst_d ,params ,stream , 391ctx .device ); 392 }else { 393soft_max_f32_sycl (src0_d , (const float * )src1_d , (const float * )src2_d , 394dst_d ,params ,stream ,ctx .device ); 395 } 396} 397 398void ggml_sycl_op_soft_max_back (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 399scope_op_debug_print scope_dbg_print (__func__ ,dst ,/*num_src=*/ 2 ); 400const ggml_tensor * src0 = dst -> src [0 ];// grad 401const ggml_tensor * src1 = dst -> src [1 ];// forward pass output 402 403const float * src0_d = (const float * )src0 -> data ; 404const float * src1_d = (const float * )src1 -> data ; 405float * dst_d = (float * )dst -> data ; 406 407 dpct::queue_ptr stream = ctx .stream (); 408 409GGML_ASSERT (src0 -> type == GGML_TYPE_F32 ); 410GGML_ASSERT (src1 -> type == GGML_TYPE_F32 ); 411GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 412 413const int64_t ncols = src0 -> ne [0 ]; 414const int64_t nrows = ggml_nrows (src0 ); 415 416float scale = 1.0f ; 417float max_bias = 0.0f ; 418 419memcpy (& scale , (const float * )dst -> op_params + 0 ,sizeof (float )); 420memcpy (& max_bias , (const float * )dst -> op_params + 1 ,sizeof (float )); 421 422GGML_ASSERT (max_bias == 0.0f ); 423 424soft_max_back_f32_sycl (src0_d ,src1_d ,dst_d ,ncols ,nrows ,scale ,stream ); 425}