char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
dbeb37548
char/aliceai-t5-moe
1#include "norm.hpp" 2#include "ggml-sycl/common.hpp" 3#include "ggml-sycl/presets.hpp" 4 5static void norm_f32 (const float * x ,float * dst ,const int ncols , 6const int64_t src_stride_col ,const int64_t src_stride_row ,const int64_t src_stride_channel ,const int64_t src_stride_sample , 7const int64_t dst_stride_col ,const int64_t dst_stride_row ,const int64_t dst_stride_channel ,const int64_t dst_stride_sample , 8const float eps ,const sycl::nd_item < 3 >& item_ct1 , sycl::float2 * s_sum ,int block_size ) { 9 10const int nthreads = item_ct1 .get_local_range (2 ); 11const int sample = item_ct1 .get_group (0 ); 12const int channel = item_ct1 .get_group (1 ); 13const int row = item_ct1 .get_group (2 ); 14 15const int tid = item_ct1 .get_local_id (2 ); 16const int nwarps = nthreads /WARP_SIZE ; 17 18const auto src_offset = calculate_offset < 3 > ({src_stride_sample ,src_stride_channel ,src_stride_row }, {sample ,channel ,row }); 19const auto dst_offset = calculate_offset < 3 > ({dst_stride_sample ,dst_stride_channel ,dst_stride_row }, {sample ,channel ,row }); 20 21x += src_offset ; 22dst += dst_offset ; 23 24 sycl::float2 mean_var = sycl::float2 (0.f ,0.f ); 25 26for (int col = tid ;col < ncols ;col += block_size ) { 27const float xi = x [col * src_stride_col ]; 28mean_var .x ()+= xi ; 29mean_var .y ()+= xi * xi ; 30 } 31 32// sum up partial sums 33mean_var = warp_reduce_sum (mean_var ,item_ct1 ); 34if (block_size > WARP_SIZE ) { 35const auto sub_group = item_ct1 .get_sub_group (); 36const auto sg_id = sub_group .get_group_linear_id (); 37const auto wi_in_sg = sub_group .get_local_linear_id (); 38if (wi_in_sg == 0 ) { 39s_sum [sg_id ]= mean_var ; 40 } 41item_ct1 .barrier (sycl::access::fence_space::local_space ); 42mean_var = 0.f ; 43const size_t nreduce = ceil_div (nwarps ,WARP_SIZE ); 44for (size_t i = 0 ;i < nreduce ;i += 1 ) 45 { 46mean_var += s_sum [wi_in_sg + i * WARP_SIZE ]; 47 } 48mean_var = warp_reduce_sum (mean_var ,item_ct1 ); 49 } 50 51const float mean = mean_var .x () /ncols ; 52const float var = mean_var .y () /ncols - mean * mean ; 53const float inv_std = sycl::rsqrt (var + eps ); 54 55for (int col = tid ;col < ncols ;col += block_size ) { 56dst [col * dst_stride_col ]= (x [col * src_stride_col ]- mean )* inv_std ; 57 } 58} 59 60static void group_norm_f32 (const float * x ,float * dst ,const int group_size ,const int ne_elements ,const float eps , 61const sycl::nd_item < 3 >& item_ct1 ,float * s_sum ,int block_size ) { 62int start = item_ct1 .get_group (2 )* group_size ; 63int end = start + group_size ; 64const int nthreads = item_ct1 .get_local_range (2 ); 65const int nwarps = nthreads /WARP_SIZE ; 66start += item_ct1 .get_local_id (2 ); 67size_t nreduce = nwarps /WARP_SIZE ; 68 69if (end >=ne_elements ) { 70end = ne_elements ; 71 } 72 73float tmp = 0.0f ;// partial sum for thread in warp 74 75for (int j = start ;j < end ;j += block_size ) { 76tmp += x [j ]; 77 } 78 79tmp = warp_reduce_sum (tmp ,item_ct1 ); 80if (block_size > WARP_SIZE ) { 81 82int warp_id = item_ct1 .get_local_id (2 ) /WARP_SIZE ; 83int lane_id = item_ct1 .get_local_id (2 ) %WARP_SIZE ; 84if (lane_id == 0 ) { 85s_sum [warp_id ]= tmp ; 86 } 87/* 88DPCT1118:1: SYCL group functions and algorithms must be encountered in 89converged control flow. You may need to adjust the code. 90*/ 91/* 92DPCT1065:54: Consider replacing sycl::nd_item::barrier() with 93sycl::nd_item::barrier(sycl::access::fence_space::local_space) for 94better performance if there is no access to global memory. 95*/ 96item_ct1 .barrier (); 97tmp = 0.f ; 98for (size_t i = 0 ;i < nreduce ;i += 1 ) 99 { 100tmp += s_sum [lane_id + i * WARP_SIZE ]; 101 } 102tmp = warp_reduce_sum (tmp ,item_ct1 ); 103 } 104 105float mean = tmp /group_size ; 106tmp = 0.0f ; 107 108for (int j = start ;j < end ;j += block_size ) { 109float xi = x [j ]- mean ; 110dst [j ]= xi ; 111tmp += xi * xi ; 112 } 113 114tmp = warp_reduce_sum (tmp ,item_ct1 ); 115if (block_size > WARP_SIZE ) { 116 117int warp_id = item_ct1 .get_local_id (2 ) /WARP_SIZE ; 118int lane_id = item_ct1 .get_local_id (2 ) %WARP_SIZE ; 119if (lane_id == 0 ) { 120s_sum [warp_id ]= tmp ; 121 } 122/* 123DPCT1118:2: SYCL group functions and algorithms must be encountered in 124converged control flow. You may need to adjust the code. 125*/ 126/* 127DPCT1065:55: Consider replacing sycl::nd_item::barrier() with 128sycl::nd_item::barrier(sycl::access::fence_space::local_space) for 129better performance if there is no access to global memory. 130*/ 131item_ct1 .barrier (); 132tmp = 0.f ; 133for (size_t i = 0 ;i < nreduce ;i += 1 ) 134 { 135tmp += s_sum [lane_id + i * WARP_SIZE ]; 136 } 137tmp = warp_reduce_sum (tmp ,item_ct1 ); 138 } 139 140float variance = tmp /group_size ; 141float scale = sycl::rsqrt (variance + eps ); 142for (int j = start ;j < end ;j += block_size ) { 143dst [j ] *=scale ; 144 } 145} 146 147template < bool do_multiply = false,bool do_add = false> 148static void rms_norm_f32 (const float * x ,float * dst ,const int ncols , 149const int64_t src_stride_col ,const int64_t src_stride_row ,const int64_t src_stride_channel ,const int64_t src_stride_sample , 150const int64_t dst_stride_col ,const int64_t dst_stride_row ,const int64_t dst_stride_channel ,const int64_t dst_stride_sample , 151const float eps ,const sycl::nd_item < 3 >& item_ct1 ,float * s_sum ,int block_size , 152const float * mul = nullptr ,const int64_t mul_stride_row = 0 ,const int64_t mul_stride_channel = 0 , 153const int64_t mul_stride_sample = 0 ,const int mul_nrows = 0 ,const int mul_nchannels = 0 ,const int mul_nsamples = 0 , 154const float * add = nullptr ,const int64_t add_stride_row = 0 ,const int64_t add_stride_channel = 0 , 155const int64_t add_stride_sample = 0 ,const int add_nrows = 0 ,const int add_nchannels = 0 ,const int add_nsamples = 0 ) { 156 157 static_assert(!do_add || do_multiply ,"fusing add is not supported without multiplying" ); 158 159const int sample = item_ct1 .get_group (0 ); 160const int channel = item_ct1 .get_group (1 ); 161const int row = item_ct1 .get_group (2 ); 162 163const int nthreads = item_ct1 .get_local_range (2 ); 164 165const int tid = item_ct1 .get_local_id (2 ); 166const int nwarps = nthreads /WARP_SIZE ; 167 168const auto src_offset = calculate_offset < 3 > ({src_stride_sample ,src_stride_channel ,src_stride_row }, {sample ,channel ,row }); 169const auto dst_offset = calculate_offset < 3 > ({dst_stride_sample ,dst_stride_channel ,dst_stride_row }, {sample ,channel ,row }); 170 171x += src_offset ; 172dst += dst_offset ; 173 174if constexpr (do_multiply ) { 175const int mul_row = row %mul_nrows ; 176const int mul_channel = channel %mul_nchannels ; 177const int mul_sample = sample %mul_nsamples ; 178mul += mul_sample * mul_stride_sample + mul_channel * mul_stride_channel + mul_row * mul_stride_row ; 179 } 180 181if constexpr (do_add ) { 182const int add_row = row %add_nrows ; 183const int add_channel = channel %add_nchannels ; 184const int add_sample = sample %add_nsamples ; 185add += add_sample * add_stride_sample + add_channel * add_stride_channel + add_row * add_stride_row ; 186 } 187 188float tmp = 0.0f ;// partial sum for thread in warp 189 190for (int col = tid ;col < ncols ;col += block_size ) { 191const float xi = x [col * src_stride_col ]; 192tmp += xi * xi ; 193 } 194 195// sum up partial sums 196tmp = warp_reduce_sum (tmp ,item_ct1 ); 197if (block_size > WARP_SIZE ) { 198const auto sub_group = item_ct1 .get_sub_group (); 199const auto sg_id = sub_group .get_group_linear_id (); 200const auto wi_in_sg = sub_group .get_local_linear_id (); 201if (wi_in_sg == 0 ) { 202s_sum [sg_id ]= tmp ; 203 } 204 205item_ct1 .barrier (sycl::access::fence_space::local_space ); 206const size_t nreduce = ceil_div (nwarps ,WARP_SIZE ); 207tmp = 0.f ; 208for (size_t i = 0 ;i < nreduce ;i += 1 ) 209 { 210tmp += s_sum [wi_in_sg + i * WARP_SIZE ]; 211 } 212tmp = warp_reduce_sum (tmp ,item_ct1 ); 213 } 214 215const float mean = tmp /ncols ; 216const float scale = sycl::rsqrt (mean + eps ); 217 218for (int col = tid ;col < ncols ;col += block_size ) { 219if constexpr (do_multiply && do_add ) { 220dst [col * dst_stride_col ]= scale * x [col * src_stride_col ]* mul [col ]+ add [col ]; 221 }else if constexpr (do_multiply ) { 222dst [col * dst_stride_col ]= scale * x [col * src_stride_col ]* mul [col ]; 223 }else { 224dst [col * dst_stride_col ]= scale * x [col * src_stride_col ]; 225 } 226 } 227} 228 229template < int warp_size > 230static void l2_norm_f32 (const float * x ,float * dst ,const int ncols , 231const int64_t src_stride_col ,const int64_t src_stride_row ,const int64_t src_stride_channel , 232const int64_t src_stride_sample ,const int64_t dst_stride_col ,const int64_t dst_stride_row , 233const int64_t dst_stride_channel ,const int64_t dst_stride_sample ,const float eps , 234const sycl::nd_item < 3 >& item_ct1 ,float * s_sum ,const int block_size ) { 235 236const int row = item_ct1 .get_group (2 ); 237const int channel = item_ct1 .get_group (1 ); 238const int sample = item_ct1 .get_group (0 ); 239const int tid = item_ct1 .get_local_id (2 ); 240 241x += sample * src_stride_sample + channel * src_stride_channel + row * src_stride_row ; 242dst += sample * dst_stride_sample + channel * dst_stride_channel + row * dst_stride_row ; 243 244float tmp = 0.0f ;// partial sum for thread in warp 245 246for (int col = tid ;col < ncols ;col += block_size ) { 247const float xi = x [col * src_stride_col ]; 248tmp += xi * xi ; 249 } 250 251tmp = block_reduce < block_reduce_method::SUM ,warp_size > (tmp ,s_sum ,block_size ); 252const float scale = sycl::rsqrt (sycl::fmax (tmp ,eps * eps )); 253 254for (int col = tid ;col < ncols ;col += block_size ) { 255dst [col * dst_stride_col ]= scale * x [col * src_stride_col ]; 256 } 257} 258 259static void norm_f32_sycl (const float * x ,float * dst ,const int ncols ,const int nrows ,const int nchannels ,const int nsamples , 260const int64_t src_stride_col ,const int64_t src_stride_row ,const int64_t src_stride_channel ,const int64_t src_stride_sample , 261const int64_t dst_stride_col ,const int64_t dst_stride_row ,const int64_t dst_stride_channel ,const int64_t dst_stride_sample , 262const float eps ,queue_ptr stream ,int device ) { 263 264const sycl::range < 3 > global_dims (nsamples ,nchannels ,nrows ); 265if (ncols < 1024 ) { 266const sycl::range < 3 > block_dims (1 ,1 ,WARP_SIZE ); 267stream -> submit ([& ](sycl::handler & cgh ) { 268cgh .parallel_for ( 269 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 270 [= ](sycl::nd_item < 3 > item_ct1 ) 271 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 272norm_f32 (x ,dst ,ncols , 273src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 274dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 275eps ,item_ct1 ,nullptr ,WARP_SIZE ); 276 }); 277 }); 278 } 279else { 280const int work_group_size = ggml_sycl_info ().max_work_group_sizes [device ]; 281assert (work_group_size % (WARP_SIZE * WARP_SIZE )== 0 ); 282const sycl::range < 3 > block_dims (1 ,1 ,work_group_size ); 283/* 284DPCT1049:17: The work-group size passed to the SYCL kernel may exceed 285the limit. To get the device limit, query 286info::device::max_work_group_size. Adjust the work-group size if needed. 287*/ 288stream -> submit ([& ](sycl::handler & cgh ) { 289 sycl::local_accessor < sycl::float2 ,1 > s_sum_acc_ct1 ( 290 sycl::range < 1 > (work_group_size /WARP_SIZE ),cgh ); 291cgh .parallel_for ( 292 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 293 [= ](sycl::nd_item < 3 > item_ct1 ) 294 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 295norm_f32 (x ,dst ,ncols , 296src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 297dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 298eps ,item_ct1 ,get_pointer (s_sum_acc_ct1 ),work_group_size ); 299 }); 300 }); 301 } 302} 303 304static void group_norm_f32_sycl (const float * x ,float * dst , 305const int num_groups ,const float eps ,const int group_size , 306const int ne_elements ,queue_ptr stream ,int device ) { 307if (group_size < 1024 ) { 308const sycl::range < 3 > block_dims (1 ,1 ,WARP_SIZE ); 309stream -> submit ([& ](sycl::handler & cgh ) { 310const float eps_ct4 = eps ; 311cgh .parallel_for ( 312 sycl::nd_range < 3 > (sycl::range < 3 > (1 ,1 ,num_groups )* block_dims , 313block_dims ), 314 [= ](sycl::nd_item < 3 > item_ct1 ) 315 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 316group_norm_f32 ( 317x ,dst ,group_size ,ne_elements ,eps_ct4 ,item_ct1 , 318nullptr ,WARP_SIZE ); 319 }); 320 }); 321 } 322else { 323const int work_group_size = ggml_sycl_info ().max_work_group_sizes [device ]; 324assert (work_group_size % (WARP_SIZE * WARP_SIZE )== 0 ); 325const sycl::range < 3 > block_dims (1 ,1 ,work_group_size ); 326/* 327DPCT1049:18: The work-group size passed to the SYCL kernel may exceed 328the limit. To get the device limit, query 329info::device::max_work_group_size. Adjust the work-group size if needed. 330*/ 331 332stream -> submit ([& ](sycl::handler & cgh ) { 333 sycl::local_accessor < float ,1 > s_sum_acc_ct1 (sycl::range < 1 > (work_group_size /WARP_SIZE ), 334cgh ); 335 336const float eps_ct4 = eps ; 337 338cgh .parallel_for ( 339 sycl::nd_range < 3 > (sycl::range < 3 > (1 ,1 ,num_groups )* block_dims , 340block_dims ), 341 [= ](sycl::nd_item < 3 > item_ct1 ) 342 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 343group_norm_f32 (x ,dst ,group_size ,ne_elements , 344eps_ct4 ,item_ct1 , 345get_pointer (s_sum_acc_ct1 ),work_group_size ); 346 }); 347 }); 348 } 349} 350 351static void rms_norm_f32_sycl (const float * x ,float * dst ,const int ncols ,const int nrows ,const int nchannels ,const int nsamples , 352const int64_t src_stride_col ,const int64_t src_stride_row ,const int64_t src_stride_channel ,const int64_t src_stride_sample , 353const int64_t dst_stride_col ,const int64_t dst_stride_row ,const int64_t dst_stride_channel ,const int64_t dst_stride_sample , 354const float eps ,queue_ptr stream ,int device ) { 355// printf("%s ncols=%d, nrows=%d, WARP_SIZE=%d\n", __func__, ncols, nrows, WARP_SIZE); 356 357const sycl::range < 3 > global_dims (nsamples ,nchannels ,nrows ); 358if (ncols < 1024 ) { 359const sycl::range < 3 > block_dims (1 ,1 ,WARP_SIZE ); 360stream -> submit ([& ](sycl::handler & cgh ) { 361cgh .parallel_for ( 362 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 363 [= ](sycl::nd_item < 3 > item_ct1 ) 364 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 365rms_norm_f32 (x ,dst ,ncols , 366src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 367dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 368eps ,item_ct1 ,nullptr ,WARP_SIZE ); 369 }); 370 }); 371 } 372else { 373const int work_group_size = ggml_sycl_info ().max_work_group_sizes [device ]; 374assert (work_group_size % (WARP_SIZE * WARP_SIZE )== 0 ); 375const sycl::range < 3 > block_dims (1 ,1 ,work_group_size ); 376/* 377DPCT1049:19: The work-group size passed to the SYCL kernel may exceed 378the limit. To get the device limit, query 379info::device::max_work_group_size. Adjust the work-group size if needed. 380*/ 381stream -> submit ([& ](sycl::handler & cgh ) { 382 sycl::local_accessor < float ,1 > s_sum_acc_ct1 (sycl::range < 1 > (work_group_size /WARP_SIZE ), 383cgh ); 384cgh .parallel_for ( 385 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 386 [= ](sycl::nd_item < 3 > item_ct1 ) 387 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 388rms_norm_f32 (x ,dst ,ncols , 389src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 390dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 391eps ,item_ct1 ,get_pointer (s_sum_acc_ct1 ),work_group_size ); 392 }); 393 }); 394 } 395} 396 397static void rms_norm_mul_f32_sycl (const float * x ,const float * mul ,float * dst ,const int ncols ,const int nrows , 398const int nchannels ,const int nsamples , 399const int64_t src_stride_col ,const int64_t src_stride_row ,const int64_t src_stride_channel ,const int64_t src_stride_sample , 400const int64_t dst_stride_col ,const int64_t dst_stride_row ,const int64_t dst_stride_channel ,const int64_t dst_stride_sample , 401const int64_t mul_stride_row ,const int64_t mul_stride_channel ,const int64_t mul_stride_sample , 402const int mul_nrows ,const int mul_nchannels ,const int mul_nsamples , 403const float eps ,queue_ptr stream ,int device ) { 404const sycl::range < 3 > global_dims (nsamples ,nchannels ,nrows ); 405if (ncols < 1024 ) { 406const sycl::range < 3 > block_dims (1 ,1 ,WARP_SIZE ); 407stream -> submit ([& ](sycl::handler & cgh ) { 408cgh .parallel_for ( 409 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 410 [= ](sycl::nd_item < 3 > item_ct1 ) 411 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 412rms_norm_f32 < true> (x ,dst ,ncols , 413src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 414dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 415eps ,item_ct1 ,nullptr ,WARP_SIZE , 416mul ,mul_stride_row ,mul_stride_channel ,mul_stride_sample ,mul_nrows ,mul_nchannels ,mul_nsamples ); 417 }); 418 }); 419 } 420else { 421const int work_group_size = ggml_sycl_info ().max_work_group_sizes [device ]; 422assert (work_group_size % (WARP_SIZE * WARP_SIZE )== 0 ); 423const sycl::range < 3 > block_dims (1 ,1 ,work_group_size ); 424stream -> submit ([& ](sycl::handler & cgh ) { 425 sycl::local_accessor < float ,1 > s_sum_acc_ct1 (sycl::range < 1 > (work_group_size /WARP_SIZE ),cgh ); 426cgh .parallel_for ( 427 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 428 [= ](sycl::nd_item < 3 > item_ct1 ) 429 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 430rms_norm_f32 < true> (x ,dst ,ncols , 431src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 432dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 433eps ,item_ct1 ,get_pointer (s_sum_acc_ct1 ),work_group_size , 434mul ,mul_stride_row ,mul_stride_channel ,mul_stride_sample ,mul_nrows ,mul_nchannels ,mul_nsamples ); 435 }); 436 }); 437 } 438} 439 440static void rms_norm_mul_add_f32_sycl (const float * x ,const float * mul ,const float * add ,float * dst , 441const int ncols ,const int nrows ,const int nchannels ,const int nsamples , 442const int64_t src_stride_col ,const int64_t src_stride_row ,const int64_t src_stride_channel ,const int64_t src_stride_sample , 443const int64_t dst_stride_col ,const int64_t dst_stride_row ,const int64_t dst_stride_channel ,const int64_t dst_stride_sample , 444const int64_t mul_stride_row ,const int64_t mul_stride_channel ,const int64_t mul_stride_sample , 445const int mul_nrows ,const int mul_nchannels ,const int mul_nsamples , 446const int64_t add_stride_row ,const int64_t add_stride_channel ,const int64_t add_stride_sample , 447const int add_nrows ,const int add_nchannels ,const int add_nsamples , 448const float eps ,queue_ptr stream ,int device ) { 449const sycl::range < 3 > global_dims (nsamples ,nchannels ,nrows ); 450if (ncols < 1024 ) { 451const sycl::range < 3 > block_dims (1 ,1 ,WARP_SIZE ); 452stream -> submit ([& ](sycl::handler & cgh ) { 453cgh .parallel_for ( 454 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 455 [= ](sycl::nd_item < 3 > item_ct1 ) 456 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 457rms_norm_f32 < true, true> (x ,dst ,ncols , 458src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 459dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 460eps ,item_ct1 ,nullptr ,WARP_SIZE , 461mul ,mul_stride_row ,mul_stride_channel ,mul_stride_sample ,mul_nrows ,mul_nchannels ,mul_nsamples , 462add ,add_stride_row ,add_stride_channel ,add_stride_sample ,add_nrows ,add_nchannels ,add_nsamples ); 463 }); 464 }); 465 } 466else { 467const int work_group_size = ggml_sycl_info ().max_work_group_sizes [device ]; 468assert (work_group_size % (WARP_SIZE * WARP_SIZE )== 0 ); 469const sycl::range < 3 > block_dims (1 ,1 ,work_group_size ); 470stream -> submit ([& ](sycl::handler & cgh ) { 471 sycl::local_accessor < float ,1 > s_sum_acc_ct1 (sycl::range < 1 > (work_group_size /WARP_SIZE ),cgh ); 472cgh .parallel_for ( 473 sycl::nd_range < 3 > (global_dims * block_dims ,block_dims ), 474 [= ](sycl::nd_item < 3 > item_ct1 ) 475 [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 476rms_norm_f32 < true, true> (x ,dst ,ncols , 477src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 478dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 479eps ,item_ct1 ,get_pointer (s_sum_acc_ct1 ),work_group_size , 480mul ,mul_stride_row ,mul_stride_channel ,mul_stride_sample ,mul_nrows ,mul_nchannels ,mul_nsamples , 481add ,add_stride_row ,add_stride_channel ,add_stride_sample ,add_nrows ,add_nchannels ,add_nsamples ); 482 }); 483 }); 484 } 485} 486 487template < int warp_size > 488static void l2_norm_f32_sycl (const float * x , 489float * dst , 490const int ncols , 491const int nrows , 492const int nchannels , 493const int nsamples , 494const int64_t src_stride_col , 495const int64_t src_stride_row , 496const int64_t src_stride_channel , 497const int64_t src_stride_sample , 498const int64_t dst_stride_col , 499const int64_t dst_stride_row , 500const int64_t dst_stride_channel , 501const int64_t dst_stride_sample , 502const float eps , 503queue_ptr stream , 504int device ) { 505const dpct::dim3 blocks_num (nrows ,nchannels ,nsamples ); 506 507if (ncols < 1024 ) { 508const dpct::dim3 block_dims (warp_size ,1 ,1 ); 509stream -> submit ([& ](sycl::handler & cgh ) { 510cgh .parallel_for ( 511 sycl::nd_range < 3 > (blocks_num * block_dims , 512block_dims ), 513 [= ](sycl::nd_item < 3 > item_ct1 ) 514 [[sycl ::reqd_sub_group_size (warp_size )]] { 515l2_norm_f32 < warp_size > (x ,dst ,ncols , 516src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 517dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 518eps ,item_ct1 , 519nullptr ,warp_size ); 520 }); 521 }); 522 } 523else { 524const int work_group_size = ggml_sycl_info ().max_work_group_sizes [device ]; 525assert (work_group_size % (warp_size * warp_size )== 0 ); 526const sycl::range < 3 > block_dims (1 ,1 ,work_group_size ); 527int lsm_size = block_dims [2 ]> warp_size ?work_group_size /warp_size * sizeof (float ):0 ; 528stream -> submit ([& ](sycl::handler & cgh ) { 529 sycl::local_accessor < float ,1 > s_sum_acc_ct1 (sycl::range < 1 > (lsm_size ), 530cgh ); 531 532cgh .parallel_for ( 533 sycl::nd_range < 3 > (blocks_num * block_dims , 534block_dims ), 535 [= ](sycl::nd_item < 3 > item_ct1 ) 536 [[sycl ::reqd_sub_group_size (warp_size )]] { 537l2_norm_f32 < warp_size > (x ,dst ,ncols , 538src_stride_col ,src_stride_row ,src_stride_channel ,src_stride_sample , 539dst_stride_col ,dst_stride_row ,dst_stride_channel ,dst_stride_sample , 540eps ,item_ct1 ,get_pointer (s_sum_acc_ct1 ),work_group_size ); 541 }); 542 }); 543 } 544} 545 546// Batched L2 norm: N independent same-shape F32 tensors in one launch; the tensor 547// index is folded into grid dim0 and each row's reduction is identical to the 548// single-tensor kernel, so the result is bit-exact. 549struct l2_batch_ptrs { 550const float * src [GGML_SYCL_L2_BATCH_MAX ]; 551float * dst [GGML_SYCL_L2_BATCH_MAX ]; 552}; 553 554// One stride set shared by the whole batch: the caller only groups tensors whose nb[] 555// all match, so per-tensor state stays two pointers. 556struct l2_batch_strides { 557int ne1 ,ne2 ; 558int64_t ss0 ,ss1 ,ss2 ,ss3 ; 559int64_t ds0 ,ds1 ,ds2 ,ds3 ; 560}; 561 562template < int warp_size > 563static void l2_norm_f32_batch (l2_batch_ptrs p ,l2_batch_strides st ,const int ncols ,const float eps , 564const sycl::nd_item < 3 > & item_ct1 ) { 565const int t = item_ct1 .get_group (0 );// tensor index 566const int r = item_ct1 .get_group (2 );// flattened row over ne1*ne2*ne3 567const int tid = item_ct1 .get_local_id (2 ); 568 569const int i1 = r %st .ne1 ; 570const int i2 = (r /st .ne1 ) %st .ne2 ; 571const int i3 = r / (st .ne1 * st .ne2 ); 572 573const float * x = p .src [t ]+ i3 * st .ss3 + i2 * st .ss2 + i1 * st .ss1 ; 574float * dst = p .dst [t ]+ i3 * st .ds3 + i2 * st .ds2 + i1 * st .ds1 ; 575 576float tmp = 0.0f ; 577for (int col = tid ;col < ncols ;col += warp_size ) { 578const float xi = x [col * st .ss0 ]; 579tmp += xi * xi ; 580 } 581tmp = block_reduce < block_reduce_method::SUM ,warp_size > (tmp , (float * )nullptr ,warp_size ); 582const float scale = sycl::rsqrt (sycl::fmax (tmp ,eps * eps )); 583for (int col = tid ;col < ncols ;col += warp_size ) { 584dst [col * st .ds0 ]= scale * x [col * st .ss0 ]; 585 } 586} 587 588template < int warp_size > 589static void l2_norm_f32_batch_sycl (l2_batch_ptrs p ,l2_batch_strides st ,const int n_tensors , 590const int ncols ,const int nrows_total ,const float eps , 591queue_ptr stream ) { 592const dpct::dim3 blocks_num (nrows_total ,1 ,n_tensors ); 593const dpct::dim3 block_dims (warp_size ,1 ,1 ); 594stream -> submit ([& ](sycl::handler & cgh ) { 595cgh .parallel_for (sycl::nd_range < 3 > (blocks_num * block_dims ,block_dims ), 596 [= ](sycl::nd_item < 3 > item_ct1 ) [[sycl ::reqd_sub_group_size (warp_size )]] { 597l2_norm_f32_batch < warp_size > (p ,st ,ncols ,eps ,item_ct1 ); 598 }); 599 }); 600} 601 602void ggml_sycl_op_norm (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 603const ggml_tensor * src0 = dst -> src [0 ]; 604 605GGML_ASSERT (dst -> src [0 ]-> type == GGML_TYPE_F32 ); 606GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 607 608GGML_TENSOR_UNARY_OP_LOCALS 609 dpct::queue_ptrmain_stream = ctx .stream (); 610SYCL_CHECK (ggml_sycl_set_device (ctx .device )); 611const float * src0_dd = static_cast < const float *> (dst -> src [0 ]-> data ); 612float * dst_dd = static_cast < float *> (dst -> data ); 613 614float eps ; 615memcpy (& eps ,dst -> op_params ,sizeof (float )); 616GGML_ASSERT (eps >=0.0f ); 617const size_t ts0 = ggml_type_size (src0 -> type ); 618const size_t tdst = ggml_type_size (dst -> type ); 619GGML_ASSERT (nb00 %ts0 == 0 && nb01 %ts0 == 0 && nb02 %ts0 == 0 && nb03 %ts0 == 0 ); 620GGML_ASSERT (nb0 %tdst == 0 && nb1 %tdst == 0 && nb2 %tdst == 0 && nb3 %tdst == 0 ); 621const int64_t ss0 = nb00 /ts0 ; 622const int64_t ss1 = nb01 /ts0 ; 623const int64_t ss2 = nb02 /ts0 ; 624const int64_t ss3 = nb03 /ts0 ; 625const int64_t ds0 = nb0 /tdst ; 626const int64_t ds1 = nb1 /tdst ; 627const int64_t ds2 = nb2 /tdst ; 628const int64_t ds3 = nb3 /tdst ; 629 630norm_f32_sycl (src0_dd ,dst_dd ,ne00 ,ne01 ,ne02 ,ne03 , 631ss0 ,ss1 ,ss2 ,ss3 ,ds0 ,ds1 ,ds2 ,ds3 ,eps ,main_stream ,ctx .device ); 632} 633 634void ggml_sycl_op_group_norm (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 635 636GGML_ASSERT (dst -> src [0 ]-> type == GGML_TYPE_F32 ); 637GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 638 639int num_groups = dst -> op_params [0 ]; 640 dpct::queue_ptr main_stream = ctx .stream (); 641SYCL_CHECK (ggml_sycl_set_device (ctx .device )); 642 643const float * src0_dd = static_cast < const float *> (dst -> src [0 ]-> data ); 644float * dst_dd = static_cast < float *> (dst -> data ); 645 646float eps ; 647memcpy (& eps ,dst -> op_params + 1 ,sizeof (float )); 648 649int group_size = dst -> src [0 ]-> ne [0 ]* dst -> src [0 ]-> ne [1 ]* ((dst -> src [0 ]-> ne [2 ]+ num_groups - 1 ) /num_groups ); 650group_norm_f32_sycl (src0_dd ,dst_dd ,num_groups ,eps ,group_size ,dst -> src [0 ]-> ne [0 ]* dst -> src [0 ]-> ne [1 ]* dst -> src [0 ]-> ne [2 ],main_stream ,ctx .device ); 651} 652 653void ggml_sycl_op_rms_norm (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 654 655const ggml_tensor * src0 = dst -> src [0 ]; 656GGML_ASSERT (dst -> src [0 ]-> type == GGML_TYPE_F32 ); 657GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 658 659 dpct::queue_ptr main_stream = ctx .stream (); 660SYCL_CHECK (ggml_sycl_set_device (ctx .device )); 661 662const float * src0_dd = static_cast < const float *> (dst -> src [0 ]-> data ); 663float * dst_dd = static_cast < float *> (dst -> data ); 664 665float eps ; 666memcpy (& eps ,dst -> op_params ,sizeof (float )); 667 668GGML_TENSOR_UNARY_OP_LOCALS 669const size_t ts0 = ggml_type_size (src0 -> type ); 670const size_t tdst = ggml_type_size (dst -> type ); 671GGML_ASSERT (nb00 %ts0 == 0 && nb01 %ts0 == 0 && nb02 %ts0 == 0 && nb03 %ts0 == 0 ); 672GGML_ASSERT (nb0 %tdst == 0 && nb1 %tdst == 0 && nb2 %tdst == 0 && nb3 %tdst == 0 ); 673const int64_t ss0 = nb00 /ts0 ; 674const int64_t ss1 = nb01 /ts0 ; 675const int64_t ss2 = nb02 /ts0 ; 676const int64_t ss3 = nb03 /ts0 ; 677const int64_t ds0 = nb0 /tdst ; 678const int64_t ds1 = nb1 /tdst ; 679const int64_t ds2 = nb2 /tdst ; 680const int64_t ds3 = nb3 /tdst ; 681rms_norm_f32_sycl (src0_dd ,dst_dd ,ne00 ,ne01 ,ne02 ,ne03 , 682ss0 ,ss1 ,ss2 ,ss3 ,ds0 ,ds1 ,ds2 ,ds3 ,eps ,main_stream ,ctx .device ); 683} 684 685void ggml_sycl_op_rms_norm_fused (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ,ggml_tensor * mul_tensor ) { 686const ggml_tensor * rms_norm_src = dst -> src [0 ]; 687float eps = 0.0f ; 688memcpy (& eps ,dst -> op_params ,sizeof (float )); 689 690const float * src0_dd = static_cast < const float *> (rms_norm_src -> data ); 691const float * mul_dd = nullptr ; 692const ggml_tensor * mul_src = nullptr ; 693if (mul_tensor -> src [0 ]== dst ) { 694mul_dd = static_cast < const float *> (mul_tensor -> src [1 ]-> data ); 695mul_src = mul_tensor -> src [1 ]; 696 }else if (mul_tensor -> src [1 ]== dst ) { 697mul_dd = static_cast < const float *> (mul_tensor -> src [0 ]-> data ); 698mul_src = mul_tensor -> src [0 ]; 699 }else { 700GGML_ASSERT (false); 701 } 702float * dst_dd = static_cast < float *> (mul_tensor -> data ); 703 704 dpct::queue_ptr main_stream = ctx .stream (); 705SYCL_CHECK (ggml_sycl_set_device (ctx .device )); 706 707GGML_ASSERT (rms_norm_src -> type == GGML_TYPE_F32 ); 708GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 709GGML_ASSERT (mul_tensor -> type == GGML_TYPE_F32 ); 710GGML_ASSERT (eps >=0.0f ); 711 712const int64_t ne00 = rms_norm_src -> ne [0 ]; 713const int64_t ne01 = rms_norm_src -> ne [1 ]; 714const int64_t ne02 = rms_norm_src -> ne [2 ]; 715const int64_t ne03 = rms_norm_src -> ne [3 ]; 716 717const size_t ts0 = ggml_type_size (rms_norm_src -> type ); 718GGML_ASSERT (rms_norm_src -> nb [0 ]== ts0 ); 719const int64_t s00 = rms_norm_src -> nb [0 ] /ts0 ; 720const int64_t s01 = rms_norm_src -> nb [1 ] /ts0 ; 721const int64_t s02 = rms_norm_src -> nb [2 ] /ts0 ; 722const int64_t s03 = rms_norm_src -> nb [3 ] /ts0 ; 723 724const size_t tdst = ggml_type_size (mul_tensor -> type ); 725GGML_ASSERT (mul_tensor -> nb [0 ]== tdst ); 726const int64_t d00 = mul_tensor -> nb [0 ] /tdst ; 727const int64_t d01 = mul_tensor -> nb [1 ] /tdst ; 728const int64_t d02 = mul_tensor -> nb [2 ] /tdst ; 729const int64_t d03 = mul_tensor -> nb [3 ] /tdst ; 730 731const size_t ts_mul = ggml_type_size (mul_src -> type ); 732GGML_ASSERT (mul_src -> nb [0 ]== ts_mul ); 733const int64_t mul_s01 = mul_src -> nb [1 ] /ts_mul ; 734const int64_t mul_s02 = mul_src -> nb [2 ] /ts_mul ; 735const int64_t mul_s03 = mul_src -> nb [3 ] /ts_mul ; 736const int mul_nrows = mul_src -> ne [1 ]; 737const int mul_nchannels = mul_src -> ne [2 ]; 738const int mul_nsamples = mul_src -> ne [3 ]; 739 740rms_norm_mul_f32_sycl (src0_dd ,mul_dd ,dst_dd ,ne00 ,ne01 ,ne02 ,ne03 , 741s00 ,s01 ,s02 ,s03 ,d00 ,d01 ,d02 ,d03 , 742mul_s01 ,mul_s02 ,mul_s03 ,mul_nrows ,mul_nchannels ,mul_nsamples ,eps ,main_stream ,ctx .device ); 743} 744 745void ggml_sycl_op_rms_norm_fused_add (ggml_backend_sycl_context & ctx ,ggml_tensor * dst , 746ggml_tensor * mul_tensor ,ggml_tensor * add_tensor ) { 747const ggml_tensor * rms_norm_src = dst -> src [0 ]; 748float eps = 0.0f ; 749memcpy (& eps ,dst -> op_params ,sizeof (float )); 750 751const float * src0_dd = static_cast < const float *> (rms_norm_src -> data ); 752const float * mul_dd = nullptr ; 753const ggml_tensor * mul_src = nullptr ; 754if (mul_tensor -> src [0 ]== dst ) { 755mul_dd = static_cast < const float *> (mul_tensor -> src [1 ]-> data ); 756mul_src = mul_tensor -> src [1 ]; 757 }else if (mul_tensor -> src [1 ]== dst ) { 758mul_dd = static_cast < const float *> (mul_tensor -> src [0 ]-> data ); 759mul_src = mul_tensor -> src [0 ]; 760 }else { 761GGML_ASSERT (false); 762 } 763 764const float * add_dd = nullptr ; 765const ggml_tensor * add_src = nullptr ; 766if (add_tensor -> src [0 ]== mul_tensor ) { 767add_dd = static_cast < const float *> (add_tensor -> src [1 ]-> data ); 768add_src = add_tensor -> src [1 ]; 769 }else if (add_tensor -> src [1 ]== mul_tensor ) { 770add_dd = static_cast < const float *> (add_tensor -> src [0 ]-> data ); 771add_src = add_tensor -> src [0 ]; 772 }else { 773GGML_ASSERT (false); 774 } 775 776float * dst_dd = static_cast < float *> (add_tensor -> data ); 777 778 dpct::queue_ptr main_stream = ctx .stream (); 779SYCL_CHECK (ggml_sycl_set_device (ctx .device )); 780 781GGML_ASSERT (rms_norm_src -> type == GGML_TYPE_F32 ); 782GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 783GGML_ASSERT (mul_tensor -> type == GGML_TYPE_F32 ); 784GGML_ASSERT (add_tensor -> type == GGML_TYPE_F32 ); 785GGML_ASSERT (eps >=0.0f ); 786 787const int64_t ne00 = rms_norm_src -> ne [0 ]; 788const int64_t ne01 = rms_norm_src -> ne [1 ]; 789const int64_t ne02 = rms_norm_src -> ne [2 ]; 790const int64_t ne03 = rms_norm_src -> ne [3 ]; 791 792const size_t ts0 = ggml_type_size (rms_norm_src -> type ); 793GGML_ASSERT (rms_norm_src -> nb [0 ]== ts0 ); 794const int64_t s00 = rms_norm_src -> nb [0 ] /ts0 ; 795const int64_t s01 = rms_norm_src -> nb [1 ] /ts0 ; 796const int64_t s02 = rms_norm_src -> nb [2 ] /ts0 ; 797const int64_t s03 = rms_norm_src -> nb [3 ] /ts0 ; 798 799const size_t tdst = ggml_type_size (add_tensor -> type ); 800GGML_ASSERT (add_tensor -> nb [0 ]== tdst ); 801const int64_t d00 = add_tensor -> nb [0 ] /tdst ; 802const int64_t d01 = add_tensor -> nb [1 ] /tdst ; 803const int64_t d02 = add_tensor -> nb [2 ] /tdst ; 804const int64_t d03 = add_tensor -> nb [3 ] /tdst ; 805 806const size_t ts_mul = ggml_type_size (mul_src -> type ); 807GGML_ASSERT (mul_src -> nb [0 ]== ts_mul ); 808const int64_t mul_s01 = mul_src -> nb [1 ] /ts_mul ; 809const int64_t mul_s02 = mul_src -> nb [2 ] /ts_mul ; 810const int64_t mul_s03 = mul_src -> nb [3 ] /ts_mul ; 811const int mul_nrows = mul_src -> ne [1 ]; 812const int mul_nchannels = mul_src -> ne [2 ]; 813const int mul_nsamples = mul_src -> ne [3 ]; 814 815const size_t ts_add = ggml_type_size (add_src -> type ); 816GGML_ASSERT (add_src -> nb [0 ]== ts_add ); 817const int64_t add_s01 = add_src -> nb [1 ] /ts_add ; 818const int64_t add_s02 = add_src -> nb [2 ] /ts_add ; 819const int64_t add_s03 = add_src -> nb [3 ] /ts_add ; 820const int add_nrows = add_src -> ne [1 ]; 821const int add_nchannels = add_src -> ne [2 ]; 822const int add_nsamples = add_src -> ne [3 ]; 823 824rms_norm_mul_add_f32_sycl (src0_dd ,mul_dd ,add_dd ,dst_dd ,ne00 ,ne01 ,ne02 ,ne03 , 825s00 ,s01 ,s02 ,s03 ,d00 ,d01 ,d02 ,d03 , 826mul_s01 ,mul_s02 ,mul_s03 ,mul_nrows ,mul_nchannels ,mul_nsamples , 827add_s01 ,add_s02 ,add_s03 ,add_nrows ,add_nchannels ,add_nsamples ,eps ,main_stream ,ctx .device ); 828} 829 830void ggml_sycl_op_rms_norm_back (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 831scope_op_debug_print scope_dbg_print (__func__ ,dst ,/*num_src=*/ 2 ); 832 833GGML_ASSERT (dst -> src [0 ]-> type == GGML_TYPE_F32 );// dz 834GGML_ASSERT (dst -> src [1 ]-> type == GGML_TYPE_F32 );// x 835GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 836 837float eps = 1e-5f ; 838 std::memcpy (& eps ,dst -> op_params ,sizeof (float )); 839if (!(eps > 0.0f )|| !std::isfinite (eps ))eps = 1e-5f ; 840 841const float * g_base = static_cast < const float *> (dst -> src [0 ]-> data );// dz 842const float * x_base = static_cast < const float *> (dst -> src [1 ]-> data );// x 843float * dx_base = static_cast < float *> (dst -> data ); 844 845const int64_t D = dst -> ne [0 ]; 846const int64_t n1 = dst -> ne [1 ],n2 = dst -> ne [2 ],n3 = dst -> ne [3 ]; (void )n3 ; 847const int64_t N = ggml_nrows (dst ); 848if (D == 0 || N == 0 )return ; 849 850const ggml_tensor * G = dst -> src [0 ]; 851const ggml_tensor * X = dst -> src [1 ]; 852const int ts = (int )ggml_type_size (X -> type ); 853GGML_ASSERT ((size_t )X -> nb [0 ]== (size_t )ts ); 854GGML_ASSERT ((size_t )G -> nb [0 ]== (size_t )ts ); 855GGML_ASSERT ((size_t )dst -> nb [0 ]== (size_t )ts ); 856 857const int64_t xs1 = X -> nb [1 ] /ts ,xs2 = X -> nb [2 ] /ts ,xs3 = X -> nb [3 ] /ts ; 858const int64_t gs1 = G -> nb [1 ] /ts ,gs2 = G -> nb [2 ] /ts ,gs3 = G -> nb [3 ] /ts ; 859const int64_t ds1 = dst -> nb [1 ] /ts ,ds2 = dst -> nb [2 ] /ts ,ds3 = dst -> nb [3 ] /ts ; 860 861 dpct::queue_ptr q = ctx .stream (); 862 863// work-group size: multiple of WARP_SIZE, capped by device and 256, and not larger than D 864const int device_max_wg = ggml_sycl_info ().max_work_group_sizes [ctx .device ]; 865auto roundup = [](int v ,int m ) {return ((v + m - 1 ) /m )* m ; }; 866int wg_cap = 256 ; 867if (device_max_wg > 0 )wg_cap = std::min (wg_cap ,device_max_wg ); 868int WG = std::max (WARP_SIZE , std::min (roundup ((int )std::min < int64_t > (D ,wg_cap ),WARP_SIZE ),wg_cap )); 869 870// FP32 path: per-thread compensated accumulation + hierarchical reduction 871q -> submit ([& ](sycl::handler & cgh ) { 872const int nwarps_loc = std::max (1 ,WG /WARP_SIZE ); 873// store one partial value per warp (xx and xg) for cross-warp reduction 874auto l_xx = sycl::local_accessor < sycl::float2 ,1 > (sycl::range < 1 > (nwarps_loc ),cgh ); 875auto l_xg = sycl::local_accessor < sycl::float2 ,1 > (sycl::range < 1 > (nwarps_loc ),cgh ); 876 877cgh .parallel_for ( 878 sycl::nd_range < 3 > (sycl::range < 3 > (1 ,1 ,N )* sycl::range < 3 > (1 ,1 ,WG ), 879 sycl::range < 3 > (1 ,1 ,WG )), 880 [= ](sycl::nd_item < 3 > item_ct1 ) [[sycl ::reqd_sub_group_size (WARP_SIZE )]] { 881const int row = item_ct1 .get_group (2 ); 882const int tid = item_ct1 .get_local_id (2 ); 883 884const int64_t i1 = row %n1 ; 885const int64_t i2 = (row /n1 ) %n2 ; 886const int64_t i3 = row / (n1 * n2 ); 887 888const float * __restrictx_row = x_base + i3 * xs3 + i2 * xs2 + i1 * xs1 ; 889const float * __restrictg_row = g_base + i3 * gs3 + i2 * gs2 + i1 * gs1 ; 890float * __restrictd_row = dx_base + i3 * ds3 + i2 * ds2 + i1 * ds1 ; 891 892// per-thread accumulation (compensated by default) 893float sum_xx = 0.f ,sum_xg = 0.f ; 894#ifndef GGML_SYCL_RMS_BACK_FAST 895float c_xx = 0.f ,c_xg = 0.f ; 896#endif 897for (int64_t col = tid ;col < D ;col += WG ) { 898const float xv = x_row [col ]; 899const float gv = g_row [col ]; 900#ifdef GGML_SYCL_RMS_BACK_FAST 901sum_xx += xv * xv ; 902sum_xg += xv * gv ; 903#else 904float y1 = xv * xv - c_xx ; 905float t1 = sum_xx + y1 ; 906c_xx = (t1 - sum_xx )- y1 ; 907sum_xx = t1 ; 908 909float y2 = xv * gv - c_xg ; 910float t2 = sum_xg + y2 ; 911c_xg = (t2 - sum_xg )- y2 ; 912sum_xg = t2 ; 913#endif 914 } 915 916// warp-level reduction 917 sycl::float2 xx = sycl::float2 (sum_xx , 918#ifndef GGML_SYCL_RMS_BACK_FAST 919c_xx 920#else 9210.f 922#endif 923 ); 924 sycl::float2 xg = sycl::float2 (sum_xg , 925#ifndef GGML_SYCL_RMS_BACK_FAST 926c_xg 927#else 9280.f 929#endif 930 ); 931xx = warp_reduce_sum (xx ,item_ct1 ); 932xg = warp_reduce_sum (xg ,item_ct1 ); 933 934// cross-warp reduction using local memory (single barrier) 935const auto sub_group = item_ct1 .get_sub_group (); 936const auto sg_id = sub_group .get_group_linear_id (); 937const auto wi_in_sg = sub_group .get_local_linear_id (); 938const int nthreads = item_ct1 .get_local_range (2 ); 939const int nwarps = nthreads /WARP_SIZE ; 940 941 sycl::float2 xx_total = xx ; 942 sycl::float2 xg_total = xg ; 943if (nwarps > 1 ) { 944if (wi_in_sg == 0 ) { 945l_xx [sg_id ]= xx ; 946l_xg [sg_id ]= xg ; 947 } 948item_ct1 .barrier (sycl::access::fence_space::local_space ); 949 950if (sg_id == 0 ) { 951const unsigned wi_u = wi_in_sg ; 952 sycl::float2 xx_first = (wi_u < static_cast < unsigned > (nwarps )) ?l_xx [wi_u ] : sycl::float2 (0.f ,0.f ); 953 sycl::float2 xg_first = (wi_u < static_cast < unsigned > (nwarps )) ?l_xg [wi_u ] : sycl::float2 (0.f ,0.f ); 954xx_total = warp_reduce_sum (xx_first ,item_ct1 ); 955xg_total = warp_reduce_sum (xg_first ,item_ct1 ); 956 }else { 957// other subgroups keep their local totals; they'll be ignored 958xx_total = xx ; 959xg_total = xg ; 960 } 961// ensure all threads see the first-subgroup result via broadcast below 962 } 963 964// compute inv_r and coeff once per row and broadcast to the whole work-group 965float inv_r = 0.f ; 966float coeff = 0.f ; 967if (tid == 0 ) { 968const float sum_xx_f = xx_total .x ()+ xx_total .y (); 969const float sum_xdz_f = xg_total .x ()+ xg_total .y (); 970const float mean_eps = sum_xx_f / (float )D + eps ; 971const float sum_eps = sum_xx_f + eps * (float )D ; 972inv_r = sycl::rsqrt (mean_eps ); 973coeff = - sum_xdz_f /sum_eps ; 974 } 975inv_r = sycl::group_broadcast (item_ct1 .get_group (),inv_r ); 976coeff = sycl::group_broadcast (item_ct1 .get_group (),coeff ); 977 978for (int64_t col = tid ;col < D ;col += WG ) { 979d_row [col ]= (g_row [col ]+ coeff * x_row [col ])* inv_r ; 980 } 981 }); 982 }); 983 984} 985 986void ggml_sycl_op_l2_norm (ggml_backend_sycl_context & ctx ,ggml_tensor * dst ) { 987const ggml_tensor * src0 = dst -> src [0 ]; 988const float * src0_d = (const float * )src0 -> data ; 989float * dst_d = (float * )dst -> data ; 990 dpct::queue_ptr stream = ctx .stream (); 991 992GGML_ASSERT (src0 -> type == GGML_TYPE_F32 ); 993GGML_ASSERT (dst -> type == GGML_TYPE_F32 ); 994 995GGML_TENSOR_UNARY_OP_LOCALS ; 996 997float eps ; 998memcpy (& eps ,dst -> op_params ,sizeof (float )); 999GGML_ASSERT (eps >=0.0f ); 1000 1001const size_t ts0 = ggml_type_size (src0 -> type ); 1002const size_t tdst = ggml_type_size (dst -> type ); 1003GGML_ASSERT (nb00 %ts0 == 0 && nb01 %ts0 == 0 && nb02 %ts0 == 0 && nb03 %ts0 == 0 ); 1004GGML_ASSERT (nb0 %tdst == 0 && nb1 %tdst == 0 && nb2 %tdst == 0 && nb3 %tdst == 0 ); 1005const int64_t ss0 = nb00 /ts0 ; 1006const int64_t ss1 = nb01 /ts0 ; 1007const int64_t ss2 = nb02 /ts0 ; 1008const int64_t ss3 = nb03 /ts0 ; 1009const int64_t ds0 = nb0 /tdst ; 1010const int64_t ds1 = nb1 /tdst ; 1011const int64_t ds2 = nb2 /tdst ; 1012const int64_t ds3 = nb3 /tdst ; 1013 1014/*support both WARP_SIZE or WARP_32_SIZE in code 1015choose by hardware for better performance 1016*/ 1017l2_norm_f32_sycl < WARP_SIZE > (src0_d ,dst_d ,ne00 ,ne01 ,ne02 ,ne03 , 1018ss0 ,ss1 ,ss2 ,ss3 ,ds0 ,ds1 ,ds2 ,ds3 ,eps ,stream ,ctx .device ); 1019} 1020 1021// nodes[0..count) are independent, same-shape, same-eps, same-nb L2_NORM ops validated 1022// by the caller; requires ncols < 1024 (the warp reduction path). 1023void ggml_sycl_l2_norm_batch (ggml_backend_sycl_context & ctx ,ggml_tensor ** nodes ,int count ) { 1024const ggml_tensor * s0 = nodes [0 ]-> src [0 ]; 1025const int ncols = (int )s0 -> ne [0 ]; 1026const int nrows_total = (int )ggml_nrows (s0 ); 1027float eps ; 1028memcpy (& eps ,nodes [0 ]-> op_params ,sizeof (float )); 1029GGML_ASSERT (eps >=0.0f ); 1030 1031l2_batch_ptrs p {}; 1032for (int t = 0 ;t < count ;++ t ) { 1033p .src [t ]= (const float * )nodes [t ]-> src [0 ]-> data ; 1034p .dst [t ]= (float * )nodes [t ]-> data ; 1035 } 1036 1037const ggml_tensor * d0 = nodes [0 ]; 1038const size_t ts = ggml_type_size (GGML_TYPE_F32 ); 1039l2_batch_strides st {}; 1040st .ne1 = (int )s0 -> ne [1 ]; 1041st .ne2 = (int )s0 -> ne [2 ]; 1042st .ss0 = s0 -> nb [0 ] /ts ;st .ss1 = s0 -> nb [1 ] /ts ;st .ss2 = s0 -> nb [2 ] /ts ;st .ss3 = s0 -> nb [3 ] /ts ; 1043st .ds0 = d0 -> nb [0 ] /ts ;st .ds1 = d0 -> nb [1 ] /ts ;st .ds2 = d0 -> nb [2 ] /ts ;st .ds3 = d0 -> nb [3 ] /ts ; 1044 1045l2_norm_f32_batch_sycl < WARP_SIZE > (p ,st ,count ,ncols ,nrows_total ,eps ,ctx .stream ()); 1046}