char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
a2878d30d
char/aliceai-t5-moe
1#include "ggml-metal-ops.h" 2 3#include "ggml.h" 4#include "ggml-impl.h" 5#include "ggml-backend-impl.h" 6 7#include "ggml-metal-impl.h" 8#include "ggml-metal-common.h" 9#include "ggml-metal-device.h" 10#include "ggml-metal-fusion.h" 11#include "ggml-metal-tuning.h" 12 13#include <cassert> 14#include <algorithm> 15#include <limits> 16#include <cmath> 17 18static ggml_metal_buffer_id ggml_metal_get_buffer_id (const ggml_tensor * t ) { 19if (!t ) { 20return {nullptr ,0 }; 21 } 22 23ggml_backend_buffer_t buffer = t -> view_src ?t -> view_src -> buffer :t -> buffer ; 24 25ggml_metal_buffer_t ctx = (ggml_metal_buffer_t )buffer -> context ; 26 27return ggml_metal_buffer_get_id (ctx ,t ); 28} 29 30struct ggml_metal_op { 31ggml_metal_op ( 32ggml_metal_device_t dev , 33ggml_metal_cmd_buf_t cmd_buf , 34ggml_cgraph * gf , 35ggml_metal_fusion_info * finfo , 36int idx_start , 37int idx_end , 38bool use_concurrency , 39bool use_capture , 40int debug_graph ) { 41this -> dev = dev ; 42this -> lib = ggml_metal_device_get_library (dev ); 43this -> enc = ggml_metal_encoder_init (cmd_buf ,use_concurrency ); 44this -> mem_ranges = ggml_mem_ranges_init (debug_graph ); 45this -> finfo = finfo ; 46this -> idx_start = idx_start ; 47this -> idx_end = idx_end ; 48this -> use_concurrency = use_concurrency ; 49this -> use_capture = use_capture ; 50this -> debug_graph = debug_graph ; 51this -> gf = gf ; 52 53idxs .reserve (gf -> n_nodes ); 54 55// filter empty nodes 56// TODO: this can be removed when the allocator starts filtering them earlier 57// https://github.com/ggml-org/llama.cpp/pull/16130#issuecomment-3327905830 58for (int i = idx_start ;i < idx_end ;i ++ ) { 59if (!ggml_op_is_empty (gf -> nodes [i ]-> op )&& !ggml_is_empty (gf -> nodes [i ])) { 60idxs .push_back (i ); 61 } 62 } 63 } 64 65 ~ggml_metal_op () { 66ggml_metal_encoder_end_encoding (this -> enc ); 67ggml_metal_encoder_free (this -> enc ); 68ggml_mem_ranges_free (this -> mem_ranges ); 69 } 70 71int n_nodes ()const { 72return idxs .size (); 73 } 74 75ggml_tensor * node (int i )const { 76assert (i >=0 && i < (int )idxs .size ()); 77return ggml_graph_node (gf ,idxs [i ]); 78 } 79 80// consult the fusion table for the longest pattern starting at i0 81// returns the matching pattern (nullptr if no fusion) and sets *n_out to the number of nodes 82const ggml_metal_fusion * can_fuse (int i0 ,enum ggml_metal_fusion_mode mode ,int * n_out )const { 83assert (use_fusion ()); 84assert (i0 >=0 && i0 < n_nodes ()); 85 86return ggml_metal_fusion_next (gf ,idxs .data (), (int )idxs .size (),i0 ,mode ,n_out ); 87 } 88 89// whether to attempt fusion; the toggle lives in the shared fusion debugging context owned 90// by the device (initialized from GGML_METAL_FUSION_DISABLE, overridable by the test) 91bool use_fusion ()const { 92return ggml_metal_fusion_info_enabled (finfo ); 93 } 94 95// record that a fusion fired, indexed by the matching table entry 96void count_fusions (const ggml_metal_fusion * fusion )const { 97ggml_metal_fusion_info_count_fusion (finfo ,fusion ); 98 } 99 100ggml_metal_device_t dev ; 101ggml_metal_library_t lib ; 102ggml_metal_encoder_t enc ; 103ggml_mem_ranges_t mem_ranges ; 104 105// shared fusion debugging context 106ggml_metal_fusion_info * finfo ; 107 108bool use_concurrency ; 109bool use_capture ; 110 111int debug_graph ; 112 113private : 114ggml_cgraph * gf ; 115 116int idx_start ; 117int idx_end ; 118 119// non-empty node indices 120 std::vector < int > idxs ; 121}; 122 123ggml_metal_op_t ggml_metal_op_init ( 124ggml_metal_device_t dev , 125ggml_metal_cmd_buf_t cmd_buf , 126ggml_cgraph * gf , 127ggml_metal_fusion_info * finfo , 128int idx_start , 129int idx_end , 130bool use_concurrency , 131bool use_capture , 132int debug_graph ) { 133ggml_metal_op_t res = new ggml_metal_op ( 134dev , 135cmd_buf , 136gf , 137finfo , 138idx_start , 139idx_end , 140use_concurrency , 141use_capture , 142debug_graph ); 143 144return res ; 145} 146 147void ggml_metal_op_free (ggml_metal_op_t ctx ) { 148delete ctx ; 149} 150 151int ggml_metal_op_n_nodes (ggml_metal_op_t ctx ) { 152return ctx -> n_nodes (); 153} 154 155static bool ggml_metal_op_concurrency_reset (ggml_metal_op_t ctx ) { 156if (!ctx -> mem_ranges ) { 157return true; 158 } 159 160ggml_metal_encoder_memory_barrier (ctx -> enc ); 161 162ggml_mem_ranges_reset (ctx -> mem_ranges ); 163 164return true; 165} 166 167static bool ggml_metal_op_concurrency_check (ggml_metal_op_t ctx ,const ggml_tensor * node ) { 168if (!ctx -> mem_ranges ) { 169return false; 170 } 171 172return ggml_mem_ranges_check (ctx -> mem_ranges ,node ); 173} 174 175static bool ggml_metal_op_concurrency_add (ggml_metal_op_t ctx ,const ggml_tensor * node ) { 176if (!ctx -> mem_ranges ) { 177return true; 178 } 179 180return ggml_mem_ranges_add (ctx -> mem_ranges ,node ); 181} 182 183static int ggml_metal_op_encode_impl (ggml_metal_op_t ctx ,int idx ) { 184struct ggml_tensor * node = ctx -> node (idx ); 185 186//GGML_LOG_INFO("%s: encoding node %3d, op = %8s\n", __func__, idx, ggml_op_name(node->op)); 187 188if (ggml_is_empty (node )) { 189return 1 ; 190 } 191 192switch (node -> op ) { 193case GGML_OP_NONE : 194case GGML_OP_RESHAPE : 195case GGML_OP_VIEW : 196case GGML_OP_TRANSPOSE : 197case GGML_OP_PERMUTE : 198 { 199// noop -> next node 200if (ctx -> debug_graph > 0 ) { 201GGML_LOG_DEBUG ("%s: node[%5d] - %-12s %s\n" ,__func__ ,idx ,ggml_op_name (node -> op ),"(noop)" ); 202 } 203 }return 1 ; 204default : 205 { 206 }break ; 207 } 208 209if (!ggml_metal_device_supports_op (ctx -> dev ,node )) { 210GGML_LOG_ERROR ("%s: error: unsupported op '%s'\n" ,__func__ ,ggml_op_desc (node )); 211GGML_ABORT ("unsupported op" ); 212 } 213 214if ((node -> flags & GGML_TENSOR_FLAG_COMPUTE )== 0 ) { 215return 1 ; 216 } 217 218int n_fuse = 1 ; 219 220// check if the current node can run concurrently with other nodes before it 221// the condition is that: 222// - the current node cannot write to any previous src or dst ranges 223// - the current node cannot read from any previous dst ranges 224// 225// if the condition is not satisfied, we put a memory barrier and clear all ranges 226// otherwise, we add the new ranges to the encoding context and process the node concurrently 227// 228 { 229const bool is_concurrent = ggml_metal_op_concurrency_check (ctx ,node ); 230 231if (!is_concurrent ) { 232ggml_metal_op_concurrency_reset (ctx ); 233 } 234 235if (ctx -> debug_graph > 0 ) { 236GGML_LOG_DEBUG ("%s: node[%5d] - %-12s %-12s %s\n" ,__func__ ,idx ,ggml_op_name (node -> op ),ggml_get_name (node ),is_concurrent ?"(concurrent)" :"" ); 237 } 238if (ctx -> debug_graph > 1 ) { 239GGML_TENSOR_LOCALS (int64_t ,ne0 ,node -> src [0 ],ne ); 240GGML_TENSOR_LOCALS (uint64_t ,nb0 ,node -> src [0 ],nb ); 241GGML_TENSOR_LOCALS (int64_t ,ne1 ,node -> src [1 ],ne ); 242GGML_TENSOR_LOCALS (uint64_t ,nb1 ,node -> src [1 ],nb ); 243GGML_TENSOR_LOCALS (int64_t ,ne2 ,node -> src [2 ],ne ); 244GGML_TENSOR_LOCALS (uint64_t ,nb2 ,node -> src [2 ],nb ); 245GGML_TENSOR_LOCALS (int64_t ,ne3 ,node -> src [3 ],ne ); 246GGML_TENSOR_LOCALS (uint64_t ,nb3 ,node -> src [3 ],nb ); 247GGML_TENSOR_LOCALS (int64_t ,ne ,node ,ne ); 248GGML_TENSOR_LOCALS (uint64_t ,nb ,node ,nb ); 249 250if (node -> src [0 ]) { 251GGML_LOG_DEBUG ("%s: src0 - %4s [%5lld, %5lld, %5lld, %5lld] [%5lld, %5lld, %5lld, %5lld], %d, %s\n" ,__func__ ,ggml_type_name (node -> src [0 ]-> type ),ne00 ,ne01 ,ne02 ,ne03 ,nb00 ,nb01 ,nb02 ,nb03 , 252ggml_is_contiguous (node -> src [0 ]),node -> src [0 ]-> name ); 253 } 254if (node -> src [1 ]) { 255GGML_LOG_DEBUG ("%s: src1 - %4s [%5lld, %5lld, %5lld, %5lld] [%5lld, %5lld, %5lld, %5lld], %d, %s\n" ,__func__ ,ggml_type_name (node -> src [1 ]-> type ),ne10 ,ne11 ,ne12 ,ne13 ,nb10 ,nb11 ,nb12 ,nb13 , 256ggml_is_contiguous (node -> src [1 ]),node -> src [1 ]-> name ); 257 } 258if (node -> src [2 ]) { 259GGML_LOG_DEBUG ("%s: src2 - %4s [%5lld, %5lld, %5lld, %5lld] [%5lld, %5lld, %5lld, %5lld], %d, %s\n" ,__func__ ,ggml_type_name (node -> src [2 ]-> type ),ne20 ,ne21 ,ne22 ,ne23 ,nb20 ,nb21 ,nb22 ,nb23 , 260ggml_is_contiguous (node -> src [2 ]),node -> src [2 ]-> name ); 261 } 262if (node -> src [3 ]) { 263GGML_LOG_DEBUG ("%s: src3 - %4s [%5lld, %5lld, %5lld, %5lld] [%5lld, %5lld, %5lld, %5lld], %d, %s\n" ,__func__ ,ggml_type_name (node -> src [3 ]-> type ),ne30 ,ne31 ,ne32 ,ne33 ,nb30 ,nb31 ,nb32 ,nb33 , 264ggml_is_contiguous (node -> src [3 ]),node -> src [3 ]-> name ); 265 } 266if (node ) { 267GGML_LOG_DEBUG ("%s: node - %4s [%5lld, %5lld, %5lld, %5lld] [%5lld, %5lld, %5lld, %5lld], 1, %s\n" ,__func__ ,ggml_type_name (node -> type ),ne0 ,ne1 ,ne2 ,ne3 ,nb0 ,nb1 ,nb2 ,nb3 , 268node -> name ); 269 } 270 } 271 } 272 273switch (node -> op ) { 274case GGML_OP_CONCAT : 275 { 276n_fuse = ggml_metal_op_concat (ctx ,idx ); 277 }break ; 278case GGML_OP_ADD : 279case GGML_OP_SUB : 280case GGML_OP_MUL : 281case GGML_OP_DIV : 282 { 283n_fuse = ggml_metal_op_bin (ctx ,idx ); 284 }break ; 285case GGML_OP_ADD_ID : 286 { 287n_fuse = ggml_metal_op_add_id (ctx ,idx ); 288 }break ; 289case GGML_OP_REPEAT : 290 { 291n_fuse = ggml_metal_op_repeat (ctx ,idx ); 292 }break ; 293case GGML_OP_ACC : 294 { 295n_fuse = ggml_metal_op_acc (ctx ,idx ); 296 }break ; 297case GGML_OP_SCALE : 298case GGML_OP_FILL : 299case GGML_OP_CLAMP : 300case GGML_OP_LEAKY_RELU : 301case GGML_OP_SQR : 302case GGML_OP_SQRT : 303case GGML_OP_SIN : 304case GGML_OP_COS : 305case GGML_OP_LOG : 306case GGML_OP_UNARY : 307 { 308n_fuse = ggml_metal_op_unary (ctx ,idx ); 309 }break ; 310case GGML_OP_SILU_BACK : 311 { 312n_fuse = ggml_metal_op_silu_back (ctx ,idx ); 313 }break ; 314case GGML_OP_GLU : 315 { 316n_fuse = ggml_metal_op_glu (ctx ,idx ); 317 }break ; 318case GGML_OP_SUM : 319 { 320n_fuse = ggml_metal_op_sum (ctx ,idx ); 321 }break ; 322case GGML_OP_SUM_ROWS : 323case GGML_OP_MEAN : 324 { 325n_fuse = ggml_metal_op_sum_rows (ctx ,idx ); 326 }break ; 327case GGML_OP_CUMSUM : 328 { 329n_fuse = ggml_metal_op_cumsum (ctx ,idx ); 330 }break ; 331case GGML_OP_LIGHTNING_INDEXER : 332 { 333n_fuse = ggml_metal_op_lightning_indexer (ctx ,idx ); 334 }break ; 335case GGML_OP_DSV4_HC_COMB : 336case GGML_OP_DSV4_HC_PRE : 337case GGML_OP_DSV4_HC_POST : 338 { 339n_fuse = ggml_metal_op_dsv4_hc (ctx ,idx ); 340 }break ; 341case GGML_OP_SOFT_MAX : 342 { 343n_fuse = ggml_metal_op_soft_max (ctx ,idx ); 344 }break ; 345case GGML_OP_SSM_CONV : 346 { 347n_fuse = ggml_metal_op_ssm_conv (ctx ,idx ); 348 }break ; 349case GGML_OP_SSM_SCAN : 350 { 351n_fuse = ggml_metal_op_ssm_scan (ctx ,idx ); 352 }break ; 353case GGML_OP_RWKV_WKV6 : 354case GGML_OP_RWKV_WKV7 : 355 { 356n_fuse = ggml_metal_op_rwkv (ctx ,idx ); 357 }break ; 358case GGML_OP_GATED_DELTA_NET : 359 { 360n_fuse = ggml_metal_op_gated_delta_net (ctx ,idx ); 361 }break ; 362case GGML_OP_SOLVE_TRI : 363 { 364n_fuse = ggml_metal_op_solve_tri (ctx ,idx ); 365 }break ; 366case GGML_OP_MUL_MAT : 367 { 368n_fuse = ggml_metal_op_mul_mat (ctx ,idx ); 369 }break ; 370case GGML_OP_MUL_MAT_ID : 371 { 372n_fuse = ggml_metal_op_mul_mat_id (ctx ,idx ); 373 }break ; 374case GGML_OP_GET_ROWS : 375 { 376n_fuse = ggml_metal_op_get_rows (ctx ,idx ); 377 }break ; 378case GGML_OP_SET_ROWS : 379 { 380n_fuse = ggml_metal_op_set_rows (ctx ,idx ); 381 }break ; 382case GGML_OP_DIAG : 383 { 384n_fuse = ggml_metal_op_diag (ctx ,idx ); 385 }break ; 386case GGML_OP_L2_NORM : 387 { 388n_fuse = ggml_metal_op_l2_norm (ctx ,idx ); 389 }break ; 390case GGML_OP_GROUP_NORM : 391 { 392n_fuse = ggml_metal_op_group_norm (ctx ,idx ); 393 }break ; 394case GGML_OP_NORM : 395case GGML_OP_RMS_NORM : 396 { 397n_fuse = ggml_metal_op_norm (ctx ,idx ); 398 }break ; 399case GGML_OP_ROPE : 400case GGML_OP_ROPE_BACK : 401 { 402n_fuse = ggml_metal_op_rope (ctx ,idx ); 403 }break ; 404case GGML_OP_IM2COL : 405 { 406n_fuse = ggml_metal_op_im2col (ctx ,idx ); 407 }break ; 408case GGML_OP_CONV_2D : 409 { 410n_fuse = ggml_metal_op_conv_2d (ctx ,idx ); 411 }break ; 412case GGML_OP_CONV_2D_DW : 413 { 414n_fuse = ggml_metal_op_conv_2d_dw (ctx ,idx ); 415 }break ; 416case GGML_OP_CONV_TRANSPOSE_1D : 417 { 418n_fuse = ggml_metal_op_conv_transpose_1d (ctx ,idx ); 419 }break ; 420case GGML_OP_CONV_TRANSPOSE_2D : 421 { 422n_fuse = ggml_metal_op_conv_transpose_2d (ctx ,idx ); 423 }break ; 424case GGML_OP_COL2IM_1D : 425 { 426n_fuse = ggml_metal_op_col2im_1d (ctx ,idx ); 427 }break ; 428case GGML_OP_CONV_3D : 429 { 430n_fuse = ggml_metal_op_conv_3d (ctx ,idx ); 431 }break ; 432case GGML_OP_UPSCALE : 433 { 434n_fuse = ggml_metal_op_upscale (ctx ,idx ); 435 }break ; 436case GGML_OP_PAD : 437 { 438n_fuse = ggml_metal_op_pad (ctx ,idx ); 439 }break ; 440case GGML_OP_PAD_REFLECT_1D : 441 { 442n_fuse = ggml_metal_op_pad_reflect_1d (ctx ,idx ); 443 }break ; 444case GGML_OP_ROLL : 445 { 446n_fuse = ggml_metal_op_roll (ctx ,idx ); 447 }break ; 448case GGML_OP_ARANGE : 449 { 450n_fuse = ggml_metal_op_arange (ctx ,idx ); 451 }break ; 452case GGML_OP_TIMESTEP_EMBEDDING : 453 { 454n_fuse = ggml_metal_op_timestep_embedding (ctx ,idx ); 455 }break ; 456case GGML_OP_ARGSORT : 457 { 458n_fuse = ggml_metal_op_argsort (ctx ,idx ); 459 }break ; 460case GGML_OP_TOP_K : 461 { 462n_fuse = ggml_metal_op_top_k (ctx ,idx ); 463 }break ; 464case GGML_OP_TRI : 465 { 466n_fuse = ggml_metal_op_tri (ctx ,idx ); 467 }break ; 468case GGML_OP_FLASH_ATTN_EXT : 469 { 470n_fuse = ggml_metal_op_flash_attn_ext (ctx ,idx ); 471 }break ; 472case GGML_OP_SET : 473 { 474n_fuse = ggml_metal_op_set (ctx ,idx ); 475 }break ; 476case GGML_OP_DUP : 477case GGML_OP_CPY : 478case GGML_OP_CONT : 479 { 480n_fuse = ggml_metal_op_cpy (ctx ,idx ); 481 }break ; 482case GGML_OP_POOL_1D : 483 { 484n_fuse = ggml_metal_op_pool_1d (ctx ,idx ); 485 }break ; 486case GGML_OP_POOL_2D : 487 { 488n_fuse = ggml_metal_op_pool_2d (ctx ,idx ); 489 }break ; 490case GGML_OP_ARGMAX : 491 { 492n_fuse = ggml_metal_op_argmax (ctx ,idx ); 493 }break ; 494case GGML_OP_OPT_STEP_ADAMW : 495 { 496n_fuse = ggml_metal_op_opt_step_adamw (ctx ,idx ); 497 }break ; 498case GGML_OP_OPT_STEP_SGD : 499 { 500n_fuse = ggml_metal_op_opt_step_sgd (ctx ,idx ); 501 }break ; 502case GGML_OP_COUNT_EQUAL : 503 { 504n_fuse = ggml_metal_op_count_equal (ctx ,idx ); 505 }break ; 506default : 507 { 508GGML_LOG_ERROR ("%s: error: node %3d, op = %8s not implemented\n" ,__func__ ,idx ,ggml_op_name (node -> op )); 509GGML_ABORT ("fatal error" ); 510 } 511 } 512 513if (ctx -> debug_graph > 0 ) { 514if (n_fuse > 1 ) { 515GGML_LOG_DEBUG ("%s: fuse %d ops\n" ,__func__ ,n_fuse ); 516 } 517 } 518 519// update the mem ranges in the encoding context 520for (int i = 0 ;i < n_fuse ;++ i ) { 521if (!ggml_metal_op_concurrency_add (ctx ,ctx -> node (idx + i ))) { 522ggml_metal_op_concurrency_reset (ctx ); 523 } 524 } 525 526return n_fuse ; 527} 528 529int ggml_metal_op_encode (ggml_metal_op_t ctx ,int idx ) { 530if (ctx -> use_capture ) { 531ggml_metal_encoder_debug_group_push (ctx -> enc ,ggml_op_desc (ctx -> node (idx ))); 532 } 533 534int res = ggml_metal_op_encode_impl (ctx ,idx ); 535if (idx + res > ctx -> n_nodes ()) { 536GGML_ABORT ("fusion error: nodes spanning multiple encoders have been fused. this indicates a bug in the fusion logic %s" , 537"https://github.com/ggml-org/llama.cpp/pull/14849" ); 538 } 539 540if (ctx -> use_capture ) { 541ggml_metal_encoder_debug_group_pop (ctx -> enc ); 542 } 543 544return res ; 545} 546 547int ggml_metal_op_concat (ggml_metal_op_t ctx ,int idx ) { 548ggml_tensor * op = ctx -> node (idx ); 549 550ggml_metal_library_t lib = ctx -> lib ; 551ggml_metal_encoder_t enc = ctx -> enc ; 552 553GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 554GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 555GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 556GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 557GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 558GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 559 560const int32_t dim = ((const int32_t * )op -> op_params )[0 ]; 561 562const bool is_q = ggml_is_quantized (op -> type ); 563 564// for quantized types, concat is done at the block level (nb0 == type_size == block size) 565int32_t ne00_arg = ne00 ; 566int32_t ne10_arg = ne10 ; 567int32_t ne0_arg = ne0 ; 568if (is_q ) { 569const int32_t blck = ggml_blck_size (op -> type ); 570GGML_ASSERT (ne00 %blck == 0 ); 571GGML_ASSERT (ne10 %blck == 0 ); 572GGML_ASSERT (ne0 %blck == 0 ); 573ne00_arg = ne00 /blck ; 574ne10_arg = ne10 /blck ; 575ne0_arg = ne0 /blck ; 576 } 577 578ggml_metal_kargs_concat args = { 579/*.ne00 =*/ ne00_arg , 580/*.ne01 =*/ ne01 , 581/*.ne02 =*/ ne02 , 582/*.ne03 =*/ ne03 , 583/*.nb00 =*/ nb00 , 584/*.nb01 =*/ nb01 , 585/*.nb02 =*/ nb02 , 586/*.nb03 =*/ nb03 , 587/*.ne10 =*/ ne10_arg , 588/*.ne11 =*/ ne11 , 589/*.ne12 =*/ ne12 , 590/*.ne13 =*/ ne13 , 591/*.nb10 =*/ nb10 , 592/*.nb11 =*/ nb11 , 593/*.nb12 =*/ nb12 , 594/*.nb13 =*/ nb13 , 595/*.ne0 =*/ ne0_arg , 596/*.ne1 =*/ ne1 , 597/*.ne2 =*/ ne2 , 598/*.ne3 =*/ ne3 , 599/*.nb0 =*/ nb0 , 600/*.nb1 =*/ nb1 , 601/*.nb2 =*/ nb2 , 602/*.nb3 =*/ nb3 , 603/*.dim =*/ dim , 604 }; 605 606auto pipeline = ggml_metal_library_get_pipeline_concat (lib ,op -> type ); 607 608ggml_metal_encoder_set_pipeline (enc ,pipeline ); 609ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 610ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 611ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 612ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 613 614int nth = std::min (256 ,ne0_arg ); 615 616// when rows are small, we can batch them together in a single threadgroup 617int nrptg = 1 ; 618if (nth < 256 ) { 619nrptg = std::min ((256 + nth - 1 ) /nth ,ne1 ); 620if (nrptg * nth > 256 ) { 621nrptg = 256 /nth ; 622 } 623 } 624 625const int nw0 = (ne1 + nrptg - 1 ) /nrptg ; 626 627ggml_metal_encoder_dispatch_threadgroups (enc ,nw0 ,ne2 ,ne3 ,nth ,nrptg ,1 ); 628 629return 1 ; 630} 631 632int ggml_metal_op_repeat (ggml_metal_op_t ctx ,int idx ) { 633ggml_tensor * op = ctx -> node (idx ); 634 635ggml_metal_library_t lib = ctx -> lib ; 636ggml_metal_encoder_t enc = ctx -> enc ; 637 638GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 639GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 640GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 641GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 642 643auto pipeline = ggml_metal_library_get_pipeline_repeat (lib ,op -> type ); 644 645ggml_metal_kargs_repeat args = { 646/*.ne00 =*/ ne00 , 647/*.ne01 =*/ ne01 , 648/*.ne02 =*/ ne02 , 649/*.ne03 =*/ ne03 , 650/*.nb00 =*/ nb00 , 651/*.nb01 =*/ nb01 , 652/*.nb02 =*/ nb02 , 653/*.nb03 =*/ nb03 , 654/*.ne0 =*/ ne0 , 655/*.ne1 =*/ ne1 , 656/*.ne2 =*/ ne2 , 657/*.ne3 =*/ ne3 , 658/*.nb0 =*/ nb0 , 659/*.nb1 =*/ nb1 , 660/*.nb2 =*/ nb2 , 661/*.nb3 =*/ nb3 , 662 }; 663 664ggml_metal_encoder_set_pipeline (enc ,pipeline ); 665ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 666ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 667ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 668 669const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne0 ); 670 671ggml_metal_encoder_dispatch_threadgroups (enc ,ne1 ,ne2 ,ne3 ,nth ,1 ,1 ); 672 673return 1 ; 674} 675 676int ggml_metal_op_acc (ggml_metal_op_t ctx ,int idx ) { 677ggml_tensor * op = ctx -> node (idx ); 678 679ggml_metal_library_t lib = ctx -> lib ; 680ggml_metal_encoder_t enc = ctx -> enc ; 681 682GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 683GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 684GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 685GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 686GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 687GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 688 689GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 ); 690GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 691GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 692 693GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 694GGML_ASSERT (ggml_is_contiguous_rows (op -> src [1 ])); 695 696const size_t pnb1 = ((const int32_t * )op -> op_params )[0 ]; 697const size_t pnb2 = ((const int32_t * )op -> op_params )[1 ]; 698const size_t pnb3 = ((const int32_t * )op -> op_params )[2 ]; 699const size_t offs = ((const int32_t * )op -> op_params )[3 ]; 700 701const bool inplace = (bool ) ((const int32_t * )op -> op_params )[4 ]; 702 703if (!inplace ) { 704// run a separate kernel to cpy src->dst 705// not sure how to avoid this 706// TODO: make a simpler cpy_bytes kernel 707 708//const id<MTLComputePipelineState> pipeline = ctx->pipelines[GGML_METAL_PIPELINE_TYPE_CPY_F32_F32].obj; 709auto pipeline = ggml_metal_library_get_pipeline_cpy (lib ,op -> src [0 ]-> type ,op -> type ); 710 711ggml_metal_kargs_cpy args = { 712/*.nk0 =*/ ne00 , 713/*.ne00 =*/ ne00 , 714/*.ne01 =*/ ne01 , 715/*.ne02 =*/ ne02 , 716/*.ne03 =*/ ne03 , 717/*.nb00 =*/ nb00 , 718/*.nb01 =*/ nb01 , 719/*.nb02 =*/ nb02 , 720/*.nb03 =*/ nb03 , 721/*.ne0 =*/ ne0 , 722/*.ne1 =*/ ne1 , 723/*.ne2 =*/ ne2 , 724/*.ne3 =*/ ne3 , 725/*.nb0 =*/ nb0 , 726/*.nb1 =*/ nb1 , 727/*.nb2 =*/ nb2 , 728/*.nb3 =*/ nb3 , 729 }; 730 731ggml_metal_encoder_set_pipeline (enc ,pipeline ); 732ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 733ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 734ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 735 736const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne00 ); 737 738ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 739 740ggml_metal_op_concurrency_reset (ctx ); 741 } 742 743ggml_metal_kargs_bin args = { 744/*.ne00 =*/ ne10 , 745/*.ne01 =*/ ne11 , 746/*.ne02 =*/ ne12 , 747/*.ne03 =*/ ne13 , 748/*.nb00 =*/ nb00 , 749/*.nb01 =*/ pnb1 , 750/*.nb02 =*/ pnb2 , 751/*.nb03 =*/ pnb3 , 752/*.ne10 =*/ ne10 , 753/*.ne11 =*/ ne11 , 754/*.ne12 =*/ ne12 , 755/*.ne13 =*/ ne13 , 756/*.nb10 =*/ nb10 , 757/*.nb11 =*/ nb11 , 758/*.nb12 =*/ nb12 , 759/*.nb13 =*/ nb13 , 760/*.ne0 =*/ ne10 , 761/*.ne1 =*/ ne11 , 762/*.ne2 =*/ ne12 , 763/*.ne3 =*/ ne13 , 764/*.nb0 =*/ nb0 , 765/*.nb1 =*/ pnb1 , 766/*.nb2 =*/ pnb2 , 767/*.nb3 =*/ pnb3 , 768/*.offs =*/ offs , 769/*.o1 =*/ {0 }, 770 }; 771 772auto pipeline = ggml_metal_library_get_pipeline_bin_one (lib ,GGML_OP_ADD ); 773 774ggml_metal_encoder_set_pipeline (enc ,pipeline ); 775ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 776ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 777ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 778ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 779 780const int nth_max = MIN (256 ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 781 782int nth = 1 ; 783 784while (2 * nth < args .ne0 && nth < nth_max ) { 785nth *=2 ; 786 } 787 788ggml_metal_encoder_dispatch_threadgroups (enc ,ne11 ,ne12 ,ne13 ,nth ,1 ,1 ); 789 790return 1 ; 791} 792 793int ggml_metal_op_unary (ggml_metal_op_t ctx ,int idx ) { 794ggml_tensor * op = ctx -> node (idx ); 795 796ggml_metal_library_t lib = ctx -> lib ; 797ggml_metal_encoder_t enc = ctx -> enc ; 798 799GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 800GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 801GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 802GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 803 804GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 805 806ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 807ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 808 809ggml_metal_kargs_unary args = { 810/*.ne00 =*/ ne00 , 811/*.ne01 =*/ ne01 , 812/*.ne02 =*/ ne02 , 813/*.ne03 =*/ ne03 , 814/*.nb00 =*/ nb00 , 815/*.nb01 =*/ nb01 , 816/*.nb02 =*/ nb02 , 817/*.nb03 =*/ nb03 , 818/*.ne0 =*/ ne0 , 819/*.ne1 =*/ ne1 , 820/*.ne2 =*/ ne2 , 821/*.ne3 =*/ ne3 , 822/*.nb0 =*/ nb0 , 823/*.nb1 =*/ nb1 , 824/*.nb2 =*/ nb2 , 825/*.nb3 =*/ nb3 , 826/*.slope =*/ 0.0 , 827/*.scale =*/ 0.0 , 828/*.bias =*/ 0.0 , 829/*.val =*/ 0.0 , 830/*.min =*/ 0.0 , 831/*.max =*/ 0.0 , 832 }; 833 834if (op -> op == GGML_OP_LEAKY_RELU ) { 835args .slope = ggml_get_op_params_f32 (op ,0 ); 836 } 837 838if (op -> op == GGML_OP_SCALE ) { 839args .scale = ggml_get_op_params_f32 (op ,0 ); 840args .bias = ggml_get_op_params_f32 (op ,1 ); 841 } 842 843if (op -> op == GGML_OP_FILL ) { 844args .val = ggml_get_op_params_f32 (op ,0 ); 845 } 846 847if (op -> op == GGML_OP_CLAMP ) { 848args .min = ggml_get_op_params_f32 (op ,0 ); 849args .max = ggml_get_op_params_f32 (op ,1 ); 850 } 851 852if (op -> op == GGML_OP_UNARY && ggml_get_unary_op (op )== GGML_UNARY_OP_XIELU ) { 853args .slope = ggml_get_op_params_f32 (op ,1 );// alpha_n 854args .scale = ggml_get_op_params_f32 (op ,2 );// alpha_p 855args .bias = ggml_get_op_params_f32 (op ,3 );// beta 856args .val = ggml_get_op_params_f32 (op ,4 );// eps 857 } 858 859auto pipeline = ggml_metal_library_get_pipeline_unary (lib ,op ); 860 861if (pipeline .c4 ) { 862args .ne00 = ne00 /4 ; 863args .ne0 = ne0 /4 ; 864 } 865 866ggml_metal_encoder_set_pipeline (enc ,pipeline ); 867ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 868ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 869ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 870 871if (pipeline .cnt ) { 872const int n = pipeline .c4 ?ggml_nelements (op )/4 :ggml_nelements (op ); 873 874ggml_metal_encoder_dispatch_threadgroups (enc ,n ,1 ,1 ,1 ,1 ,1 ); 875 }else { 876const int nth_max = MIN (256 ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 877const int nth = MIN (args .ne00 ,nth_max ); 878const int nk0 = (args .ne00 + nth - 1 )/nth ; 879 880ggml_metal_encoder_dispatch_threadgroups (enc ,nk0 * ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 881 } 882 883return 1 ; 884} 885 886int ggml_metal_op_glu (ggml_metal_op_t ctx ,int idx ) { 887ggml_tensor * op = ctx -> node (idx ); 888 889ggml_metal_library_t lib = ctx -> lib ; 890ggml_metal_encoder_t enc = ctx -> enc ; 891 892GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 893GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 894GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 895GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 896GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 897GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 898 899if (op -> src [1 ]) { 900GGML_ASSERT (ggml_are_same_shape (op -> src [0 ],op -> src [1 ])); 901 } 902 903auto pipeline = ggml_metal_library_get_pipeline_glu (lib ,op ); 904 905const int32_t swp = ggml_get_op_params_i32 (op ,1 ); 906const float alpha = ggml_get_op_params_f32 (op ,2 ); 907const float limit = ggml_get_op_params_f32 (op ,3 ); 908 909const int32_t i00 = swp ?ne0 :0 ; 910const int32_t i10 = swp ?0 :ne0 ; 911 912ggml_metal_kargs_glu args = { 913/*.ne00 =*/ ne00 , 914/*.nb01 =*/ nb01 , 915/*.ne10 =*/ op -> src [1 ] ?ne10 :ne00 , 916/*.nb11 =*/ op -> src [1 ] ?nb11 :nb01 , 917/*.ne0 =*/ ne0 , 918/*.nb1 =*/ nb1 , 919/*.i00 =*/ op -> src [1 ] ?0 :i00 , 920/*.i10 =*/ op -> src [1 ] ?0 :i10 , 921/*.alpha=*/ alpha , 922/*.limit=*/ limit 923 }; 924 925const int64_t nrows = ggml_nrows (op -> src [0 ]); 926 927const int32_t nth = std::max (1 , std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne00 /2 )); 928 929ggml_metal_encoder_set_pipeline (enc ,pipeline ); 930ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 931ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 932if (op -> src [1 ]) { 933ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 934 }else { 935ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),2 ); 936 } 937ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 938 939ggml_metal_encoder_dispatch_threadgroups (enc ,nrows ,1 ,1 ,nth ,1 ,1 ); 940 941return 1 ; 942} 943 944int ggml_metal_op_sum (ggml_metal_op_t ctx ,int idx ) { 945ggml_tensor * op = ctx -> node (idx ); 946 947ggml_metal_library_t lib = ctx -> lib ; 948ggml_metal_encoder_t enc = ctx -> enc ; 949 950const uint64_t n = (uint64_t )ggml_nelements (op -> src [0 ]); 951 952ggml_metal_kargs_sum args = { 953/*.np =*/ n , 954 }; 955 956auto pipeline = ggml_metal_library_get_pipeline_sum (lib ,op ); 957 958int nth = 32 ;// SIMD width 959 960while (nth < (int )n && nth < ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 961nth *=2 ; 962 } 963 964nth = std::min (nth ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 965nth = std::min (nth , (int )n ); 966 967const int nsg = (nth + 31 ) /32 ; 968 969ggml_metal_encoder_set_pipeline (enc ,pipeline ); 970ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 971ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 972ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 973 974ggml_metal_encoder_set_threadgroup_memory_size (enc ,GGML_PAD (nsg * sizeof (float ),16 ),0 ); 975 976ggml_metal_encoder_dispatch_threadgroups (enc ,1 ,1 ,1 ,nth ,1 ,1 ); 977 978return 1 ; 979} 980 981int ggml_metal_op_sum_rows (ggml_metal_op_t ctx ,int idx ) { 982ggml_tensor * op = ctx -> node (idx ); 983 984ggml_metal_library_t lib = ctx -> lib ; 985ggml_metal_encoder_t enc = ctx -> enc ; 986 987GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 988GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 989GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 990GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 991 992GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 993 994ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 995ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 996 997ggml_metal_kargs_sum_rows args = { 998/*.ne00 =*/ ne00 , 999/*.ne01 =*/ ne01 , 1000/*.ne02 =*/ ne02 , 1001/*.ne03 =*/ ne03 , 1002/*.nb00 =*/ nb00 , 1003/*.nb01 =*/ nb01 , 1004/*.nb02 =*/ nb02 , 1005/*.nb03 =*/ nb03 , 1006/*.ne0 =*/ ne0 , 1007/*.ne1 =*/ ne1 , 1008/*.ne2 =*/ ne2 , 1009/*.ne3 =*/ ne3 , 1010/*.nb0 =*/ nb0 , 1011/*.nb1 =*/ nb1 , 1012/*.nb2 =*/ nb2 , 1013/*.nb3 =*/ nb3 , 1014 }; 1015 1016auto pipeline = ggml_metal_library_get_pipeline_sum_rows (lib ,op ); 1017 1018if (pipeline .c4 ) { 1019args .ne00 = ne00 /4 ; 1020args .ne0 = ne0 /4 ; 1021 } 1022 1023int nth = 32 ;// SIMD width 1024 1025while (nth < args .ne00 && nth < ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 1026nth *=2 ; 1027 } 1028 1029nth = std::min (nth ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 1030nth = std::min (nth , (int )args .ne00 ); 1031 1032const size_t smem = pipeline .smem ; 1033 1034ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1035ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1036ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 1037ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 1038 1039ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 1040 1041ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 1042 1043return 1 ; 1044} 1045 1046int ggml_metal_op_cumsum (ggml_metal_op_t ctx ,int idx ) { 1047ggml_tensor * op = ctx -> node (idx ); 1048 1049ggml_metal_library_t lib = ctx -> lib ; 1050ggml_metal_encoder_t enc = ctx -> enc ; 1051 1052GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 1053 1054GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1055GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1056GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1057GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1058 1059auto pipeline_blk = ggml_metal_library_get_pipeline_cumsum_blk (lib ,op ); 1060 1061int nth = 1 ; 1062while (nth < ne00 && 2 * nth <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline_blk )) { 1063nth *=2 ; 1064 } 1065 1066GGML_ASSERT (ne00 <=nth * nth ); 1067 1068const int64_t net0 = (ne00 + nth - 1 ) /nth ; 1069const int64_t net1 = ne01 ; 1070const int64_t net2 = ne02 ; 1071const int64_t net3 = ne03 ; 1072 1073const uint64_t nbt0 = sizeof (float ); 1074const uint64_t nbt1 = net0 * nbt0 ; 1075const uint64_t nbt2 = net1 * nbt1 ; 1076const uint64_t nbt3 = net2 * nbt2 ; 1077 1078const size_t smem = GGML_PAD (32 * sizeof (float ),16 ); 1079 1080ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 1081ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 1082 1083ggml_metal_buffer_id bid_tmp = bid_dst ; 1084bid_tmp .offs += ggml_nbytes (op ); 1085 1086 { 1087ggml_metal_kargs_cumsum_blk args = { 1088/*.ne00 =*/ ne00 , 1089/*.ne01 =*/ ne01 , 1090/*.ne02 =*/ ne02 , 1091/*.ne03 =*/ ne03 , 1092/*.nb00 =*/ nb00 , 1093/*.nb01 =*/ nb01 , 1094/*.nb02 =*/ nb02 , 1095/*.nb03 =*/ nb03 , 1096/*.net0 =*/ net0 , 1097/*.net1 =*/ net1 , 1098/*.net2 =*/ net2 , 1099/*.net3 =*/ net3 , 1100/*.nbt0 =*/ nbt0 , 1101/*.nbt1 =*/ nbt1 , 1102/*.nbt2 =*/ nbt2 , 1103/*.nbt3 =*/ nbt3 , 1104/*.outb =*/ ne00 > nth , 1105 }; 1106 1107ggml_metal_encoder_set_pipeline (enc ,pipeline_blk ); 1108ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1109ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 1110ggml_metal_encoder_set_buffer (enc ,bid_tmp ,2 ); 1111ggml_metal_encoder_set_buffer (enc ,bid_dst ,3 ); 1112 1113ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 1114 1115ggml_metal_encoder_dispatch_threadgroups (enc ,net0 * ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 1116 } 1117 1118if (ne00 > nth ) { 1119ggml_metal_op_concurrency_reset (ctx ); 1120 1121 { 1122ggml_metal_kargs_cumsum_blk args = { 1123/*.ne00 =*/ net0 , 1124/*.ne01 =*/ net1 , 1125/*.ne02 =*/ net2 , 1126/*.ne03 =*/ net3 , 1127/*.nb00 =*/ nbt0 , 1128/*.nb01 =*/ nbt1 , 1129/*.nb02 =*/ nbt2 , 1130/*.nb03 =*/ nbt3 , 1131/*.net0 =*/ net0 , 1132/*.net1 =*/ net1 , 1133/*.net2 =*/ net2 , 1134/*.net3 =*/ net3 , 1135/*.nbt0 =*/ nbt0 , 1136/*.nbt1 =*/ nbt1 , 1137/*.nbt2 =*/ nbt2 , 1138/*.nbt3 =*/ nbt3 , 1139/*.outb =*/ false, 1140 }; 1141 1142ggml_metal_encoder_set_pipeline (enc ,pipeline_blk ); 1143ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1144ggml_metal_encoder_set_buffer (enc ,bid_tmp ,1 ); 1145ggml_metal_encoder_set_buffer (enc ,bid_tmp ,2 ); 1146ggml_metal_encoder_set_buffer (enc ,bid_tmp ,3 ); 1147 1148ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 1149 1150ggml_metal_encoder_dispatch_threadgroups (enc ,net1 ,net2 ,net3 ,nth ,1 ,1 ); 1151 } 1152 1153ggml_metal_op_concurrency_reset (ctx ); 1154 1155 { 1156auto pipeline_add = ggml_metal_library_get_pipeline_cumsum_add (lib ,op ); 1157 1158ggml_metal_kargs_cumsum_add args = { 1159/*.ne00 =*/ ne00 , 1160/*.ne01 =*/ ne01 , 1161/*.ne02 =*/ ne02 , 1162/*.ne03 =*/ ne03 , 1163/*.nb00 =*/ nb00 , 1164/*.nb01 =*/ nb01 , 1165/*.nb02 =*/ nb02 , 1166/*.nb03 =*/ nb03 , 1167/*.net0 =*/ net0 , 1168/*.net1 =*/ net1 , 1169/*.net2 =*/ net2 , 1170/*.net3 =*/ net3 , 1171/*.nbt0 =*/ nbt0 , 1172/*.nbt1 =*/ nbt1 , 1173/*.nbt2 =*/ nbt2 , 1174/*.nbt3 =*/ nbt3 , 1175 }; 1176 1177ggml_metal_encoder_set_pipeline (enc ,pipeline_add ); 1178ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1179ggml_metal_encoder_set_buffer (enc ,bid_tmp ,1 ); 1180ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 1181 1182ggml_metal_encoder_dispatch_threadgroups (enc ,net0 * ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 1183 } 1184 } 1185 1186return 1 ; 1187} 1188 1189int ggml_metal_op_get_rows (ggml_metal_op_t ctx ,int idx ) { 1190ggml_tensor * op = ctx -> node (idx ); 1191 1192ggml_metal_library_t lib = ctx -> lib ; 1193ggml_metal_encoder_t enc = ctx -> enc ; 1194 1195GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1196GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1197GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1198GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 1199GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1200GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1201 1202auto pipeline = ggml_metal_library_get_pipeline_get_rows (lib ,op -> src [0 ]-> type ); 1203 1204ggml_metal_kargs_get_rows args = { 1205/*.ne00t =*/ ggml_is_quantized (op -> src [0 ]-> type ) ?ne00 /16 :ne00 , 1206/*.ne00 =*/ ne00 , 1207/*.nb01 =*/ nb01 , 1208/*.nb02 =*/ nb02 , 1209/*.nb03 =*/ nb03 , 1210/*.ne10 =*/ ne10 , 1211/*.nb10 =*/ nb10 , 1212/*.nb11 =*/ nb11 , 1213/*.nb12 =*/ nb12 , 1214/*.nb1 =*/ nb1 , 1215/*.nb2 =*/ nb2 , 1216/*.nb3 =*/ nb3 , 1217 }; 1218 1219const int nth = std::min (args .ne00t ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 1220 1221const int nw0 = (args .ne00t + nth - 1 )/nth ; 1222 1223ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1224ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1225ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 1226ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 1227ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 1228 1229ggml_metal_encoder_dispatch_threadgroups (enc ,nw0 * ne10 ,ne11 ,ne12 ,nth ,1 ,1 ); 1230 1231return 1 ; 1232} 1233 1234int ggml_metal_op_set_rows (ggml_metal_op_t ctx ,int idx ) { 1235ggml_tensor * op = ctx -> node (idx ); 1236 1237ggml_metal_library_t lib = ctx -> lib ; 1238ggml_metal_encoder_t enc = ctx -> enc ; 1239 1240GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1241GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1242GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1243GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 1244GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1245GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1246 1247auto pipeline = ggml_metal_library_get_pipeline_set_rows (lib ,op ); 1248 1249const int32_t nk0 = ne0 /ggml_blck_size (op -> type ); 1250 1251int nth = 32 ;// SIMD width 1252 1253while (nth < nk0 && nth < ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 1254nth *=2 ; 1255 } 1256 1257int nrptg = 1 ; 1258if (nth > nk0 ) { 1259nrptg = (nth + nk0 - 1 )/nk0 ; 1260nth = nk0 ; 1261 1262if (nrptg * nth > ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 1263nrptg -- ; 1264 } 1265 } 1266 1267nth = std::min (nth ,nk0 ); 1268 1269ggml_metal_kargs_set_rows args = { 1270/*.nk0 =*/ nk0 , 1271/*.ne01 =*/ ne01 , 1272/*.nb01 =*/ nb01 , 1273/*.nb02 =*/ nb02 , 1274/*.nb03 =*/ nb03 , 1275/*.ne11 =*/ ne11 , 1276/*.ne12 =*/ ne12 , 1277/*.nb10 =*/ nb10 , 1278/*.nb11 =*/ nb11 , 1279/*.nb12 =*/ nb12 , 1280/*.nb1 =*/ nb1 , 1281/*.nb2 =*/ nb2 , 1282/*.nb3 =*/ nb3 , 1283 }; 1284 1285ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1286ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1287ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 1288ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 1289ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 1290 1291ggml_metal_encoder_dispatch_threadgroups (enc , (ne01 + nrptg - 1 )/nrptg ,ne02 ,ne03 ,nth ,nrptg ,1 ); 1292 1293return 1 ; 1294} 1295 1296int ggml_metal_op_diag (ggml_metal_op_t ctx ,int idx ) { 1297ggml_tensor * op = ctx -> node (idx ); 1298 1299ggml_metal_library_t lib = ctx -> lib ; 1300ggml_metal_encoder_t enc = ctx -> enc ; 1301 1302GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1303GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1304GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1305GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1306 1307ggml_metal_kargs_diag args = { 1308/*.ne00 =*/ ne00 , 1309/*.ne01 =*/ ne01 , 1310/*.ne02 =*/ ne02 , 1311/*.ne03 =*/ ne03 , 1312/*.nb00 =*/ nb00 , 1313/*.nb01 =*/ nb01 , 1314/*.nb02 =*/ nb02 , 1315/*.nb03 =*/ nb03 , 1316/*.ne0 =*/ ne0 , 1317/*.ne1 =*/ ne1 , 1318/*.ne2 =*/ ne2 , 1319/*.ne3 =*/ ne3 , 1320/*.nb0 =*/ nb0 , 1321/*.nb1 =*/ nb1 , 1322/*.nb2 =*/ nb2 , 1323/*.nb3 =*/ nb3 , 1324 }; 1325 1326auto pipeline = ggml_metal_library_get_pipeline_diag (lib ,op ); 1327 1328ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1329ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1330ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 1331ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 1332 1333ggml_metal_encoder_dispatch_threadgroups (enc ,ne1 ,ne2 ,ne3 ,32 ,1 ,1 ); 1334 1335return 1 ; 1336} 1337 1338int ggml_metal_op_lightning_indexer (ggml_metal_op_t ctx ,int idx ) { 1339ggml_tensor * op = ctx -> node (idx ); 1340 1341ggml_metal_encoder_t enc = ctx -> enc ; 1342 1343GGML_ASSERT (op -> op == GGML_OP_LIGHTNING_INDEXER ); 1344 1345const ggml_tensor * q = op -> src [0 ]; 1346const ggml_tensor * k = op -> src [1 ]; 1347const ggml_tensor * w = op -> src [2 ]; 1348const ggml_tensor * m = op -> src [3 ]; 1349 1350GGML_ASSERT (q -> type == GGML_TYPE_F32 ); 1351GGML_ASSERT (k -> type == GGML_TYPE_F32 || 1352k -> type == GGML_TYPE_F16 || 1353k -> type == GGML_TYPE_BF16 || 1354k -> type == GGML_TYPE_Q4_0 || 1355k -> type == GGML_TYPE_Q4_1 || 1356k -> type == GGML_TYPE_Q5_0 || 1357k -> type == GGML_TYPE_Q5_1 || 1358k -> type == GGML_TYPE_Q8_0 ); 1359GGML_ASSERT (w -> type == GGML_TYPE_F32 ); 1360GGML_ASSERT (m -> type == GGML_TYPE_F16 ); 1361GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 1362 1363GGML_ASSERT (q -> ne [0 ]== OP_LIGHTNING_INDEXER_DK ); 1364GGML_ASSERT (q -> ne [1 ]== OP_LIGHTNING_INDEXER_NH ); 1365 1366ggml_metal_kargs_lightning_indexer args = { 1367/*.n_kv =*/ (int32_t )k -> ne [2 ], 1368/*.n_batch =*/ (int32_t )q -> ne [2 ], 1369/*.mask_ne3 =*/ (int32_t )m -> ne [3 ], 1370/*.nb1 =*/ op -> nb [1 ], 1371/*.nb3 =*/ op -> nb [3 ], 1372/*.nbq1 =*/ q -> nb [1 ], 1373/*.nbq2 =*/ q -> nb [2 ], 1374/*.nbq3 =*/ q -> nb [3 ], 1375/*.nbk2 =*/ k -> nb [2 ], 1376/*.nbk3 =*/ k -> nb [3 ], 1377/*.nbw1 =*/ w -> nb [1 ], 1378/*.nbw3 =*/ w -> nb [3 ], 1379/*.nbm1 =*/ m -> nb [1 ], 1380/*.nbm3 =*/ m -> nb [3 ], 1381 }; 1382 1383ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (q ),1 ); 1384ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (k ),2 ); 1385ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (w ),3 ); 1386ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (m ),4 ); 1387ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),5 ); 1388 1389const int nsg = OP_LIGHTNING_INDEXER_NSG ; 1390const int nkptg = OP_LIGHTNING_INDEXER_NKPSG * nsg ; 1391const int nbptg = OP_LIGHTNING_INDEXER_NBPTG ; 1392 1393auto pipeline = ggml_metal_library_get_pipeline_lightning_indexer (ctx -> lib ,op ); 1394ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1395ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1396ggml_metal_encoder_dispatch_threadgroups (enc , 1397 (k -> ne [2 ]+ nkptg - 1 )/nkptg , 1398 (q -> ne [2 ]+ nbptg - 1 )/nbptg , 1399q -> ne [3 ],32 ,nsg ,1 ); 1400 1401return 1 ; 1402} 1403 1404int ggml_metal_op_dsv4_hc (ggml_metal_op_t ctx ,int idx ) { 1405ggml_tensor * op = ctx -> node (idx ); 1406 1407ggml_metal_encoder_t enc = ctx -> enc ; 1408auto pipeline = ggml_metal_library_get_pipeline_dsv4_hc (ctx -> lib ,op -> op ); 1409 1410ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1411 1412switch (op -> op ) { 1413case GGML_OP_DSV4_HC_COMB : 1414 { 1415const ggml_tensor * mixes = op -> src [0 ]; 1416const ggml_tensor * scale = op -> src [1 ]; 1417const ggml_tensor * base = op -> src [2 ]; 1418 1419GGML_ASSERT (mixes -> type == GGML_TYPE_F32 ); 1420GGML_ASSERT (scale -> type == GGML_TYPE_F32 ); 1421GGML_ASSERT (base -> type == GGML_TYPE_F32 ); 1422GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 1423GGML_ASSERT (mixes -> ne [0 ]== 24 ); 1424GGML_ASSERT (op -> ne [0 ]== 4 && op -> ne [1 ]== 4 ); 1425 1426ggml_metal_kargs_dsv4_hc_comb args = { 1427/*.n_tokens =*/ (int32_t )mixes -> ne [1 ], 1428/*.n_iter =*/ ggml_get_op_params_i32 (op ,1 ), 1429/*.nb_m0 =*/ mixes -> nb [0 ], 1430/*.nb_m1 =*/ mixes -> nb [1 ], 1431/*.nb_s0 =*/ scale -> nb [0 ], 1432/*.nb_b0 =*/ base -> nb [0 ], 1433/*.nb_d0 =*/ op -> nb [0 ], 1434/*.nb_d1 =*/ op -> nb [1 ], 1435/*.nb_d2 =*/ op -> nb [2 ], 1436/*.eps =*/ ggml_get_op_params_f32 (op ,0 ), 1437 }; 1438 1439ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1440ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (mixes ),1 ); 1441ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (scale ),2 ); 1442ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (base ),3 ); 1443ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),4 ); 1444 1445// One SIMDgroup owns one 4x4 Sinkhorn matrix. Packing up to four 1446// independent tokens per threadgroup keeps both decode and prompt 1447// dispatches compact without any threadgroup-memory synchronization. 1448const int nsg = std::min (4 ,args .n_tokens ); 1449ggml_metal_encoder_dispatch_threadgroups ( 1450enc , (args .n_tokens + nsg - 1 )/nsg ,1 ,1 ,32 ,nsg ,1 ); 1451 }break ; 1452case GGML_OP_DSV4_HC_PRE : 1453 { 1454const ggml_tensor * x = op -> src [0 ]; 1455const ggml_tensor * weights = op -> src [1 ]; 1456 1457GGML_ASSERT (x -> type == GGML_TYPE_F32 ); 1458GGML_ASSERT (weights -> type == GGML_TYPE_F32 ); 1459GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 1460GGML_ASSERT (x -> ne [1 ]== 4 ); 1461 1462ggml_metal_kargs_dsv4_hc_pre args = { 1463/*.n_embd =*/ (int32_t )x -> ne [0 ], 1464/*.n_tokens =*/ (int32_t )x -> ne [2 ], 1465/*.nb_x0 =*/ x -> nb [0 ], 1466/*.nb_x1 =*/ x -> nb [1 ], 1467/*.nb_x2 =*/ x -> nb [2 ], 1468/*.nb_w0 =*/ weights -> nb [0 ], 1469/*.nb_w1 =*/ weights -> nb [1 ], 1470/*.nb_d0 =*/ op -> nb [0 ], 1471/*.nb_d1 =*/ op -> nb [1 ], 1472 }; 1473 1474ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1475ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (x ),1 ); 1476ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (weights ),2 ); 1477ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 1478 1479const int n_tiles = (args .n_embd + 31 )/32 ; 1480const int nsg = std::min (4 ,n_tiles ); 1481ggml_metal_encoder_dispatch_threadgroups ( 1482enc , (n_tiles + nsg - 1 )/nsg ,args .n_tokens ,1 ,32 ,nsg ,1 ); 1483 }break ; 1484case GGML_OP_DSV4_HC_POST : 1485 { 1486const ggml_tensor * x = op -> src [0 ]; 1487const ggml_tensor * residual = op -> src [1 ]; 1488const ggml_tensor * post = op -> src [2 ]; 1489const ggml_tensor * comb = op -> src [3 ]; 1490 1491GGML_ASSERT (x -> type == GGML_TYPE_F32 ); 1492GGML_ASSERT (residual -> type == GGML_TYPE_F32 ); 1493GGML_ASSERT (post -> type == GGML_TYPE_F32 ); 1494GGML_ASSERT (comb -> type == GGML_TYPE_F32 ); 1495GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 1496GGML_ASSERT (residual -> ne [1 ]== 4 ); 1497 1498ggml_metal_kargs_dsv4_hc_post args = { 1499/*.n_embd =*/ (int32_t )x -> ne [0 ], 1500/*.n_tokens =*/ (int32_t )x -> ne [1 ], 1501/*.nb_x0 =*/ x -> nb [0 ], 1502/*.nb_x1 =*/ x -> nb [1 ], 1503/*.nb_r0 =*/ residual -> nb [0 ], 1504/*.nb_r1 =*/ residual -> nb [1 ], 1505/*.nb_r2 =*/ residual -> nb [2 ], 1506/*.nb_p0 =*/ post -> nb [0 ], 1507/*.nb_p1 =*/ post -> nb [1 ], 1508/*.nb_c0 =*/ comb -> nb [0 ], 1509/*.nb_c1 =*/ comb -> nb [1 ], 1510/*.nb_c2 =*/ comb -> nb [2 ], 1511/*.nb_d0 =*/ op -> nb [0 ], 1512/*.nb_d1 =*/ op -> nb [1 ], 1513/*.nb_d2 =*/ op -> nb [2 ], 1514 }; 1515 1516ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1517ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (x ),1 ); 1518ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (residual ),2 ); 1519ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (post ),3 ); 1520ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (comb ),4 ); 1521ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),5 ); 1522 1523const int n_tiles = (args .n_embd + 31 )/32 ; 1524const int nsg = std::min (4 ,n_tiles ); 1525ggml_metal_encoder_dispatch_threadgroups ( 1526enc , (n_tiles + nsg - 1 )/nsg ,args .n_tokens ,1 ,32 ,nsg ,1 ); 1527 }break ; 1528default : 1529GGML_ABORT ("fatal error" ); 1530 } 1531 1532return 1 ; 1533} 1534 1535int ggml_metal_op_soft_max (ggml_metal_op_t ctx ,int idx ) { 1536ggml_tensor * op = ctx -> node (idx ); 1537 1538ggml_metal_library_t lib = ctx -> lib ; 1539ggml_metal_encoder_t enc = ctx -> enc ; 1540 1541GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1542GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1543GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1544GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 1545GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 1546GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 1547GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1548GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1549 1550float scale ; 1551float max_bias ; 1552 1553memcpy (& scale , ((const int32_t * )op -> op_params )+ 0 ,sizeof (scale )); 1554memcpy (& max_bias , ((const int32_t * )op -> op_params )+ 1 ,sizeof (max_bias )); 1555 1556const uint32_t n_head = op -> src [0 ]-> ne [2 ]; 1557const int32_t n_head_log2 = 1u << (uint32_t )floorf (log2f ((float )n_head )); 1558 1559const float m0 = powf (2.0f ,- (max_bias ) /n_head_log2 ); 1560const float m1 = powf (2.0f ,- (max_bias /2.0f ) /n_head_log2 ); 1561 1562// softmax 1563 1564ggml_metal_kargs_soft_max args = { 1565/*.ne00 =*/ ne00 , 1566/*.ne01 =*/ ne01 , 1567/*.ne02 =*/ ne02 , 1568/*.nb01 =*/ nb01 , 1569/*.nb02 =*/ nb02 , 1570/*.nb03 =*/ nb03 , 1571/*.ne11 =*/ ne11 , 1572/*.ne12 =*/ ne12 , 1573/*.ne13 =*/ ne13 , 1574/*.nb11 =*/ nb11 , 1575/*.nb12 =*/ nb12 , 1576/*.nb13 =*/ nb13 , 1577/*.nb1 =*/ nb1 , 1578/*.nb2 =*/ nb2 , 1579/*.nb3 =*/ nb3 , 1580/*.scale =*/ scale , 1581/*.max_bias =*/ max_bias , 1582/*.m0 =*/ m0 , 1583/*.m1 =*/ m1 , 1584/*.n_head_log2 =*/ n_head_log2 , 1585 }; 1586 1587auto pipeline = ggml_metal_library_get_pipeline_soft_max (lib ,op ); 1588 1589int nth = 32 ;// SIMD width 1590 1591if (ne00 %4 == 0 ) { 1592while (nth < ne00 /4 && nth * ne01 * ne02 * ne03 < 256 ) { 1593nth *=2 ; 1594 } 1595 }else { 1596while (nth < ne00 && nth * ne01 * ne02 * ne03 < 256 ) { 1597nth *=2 ; 1598 } 1599 } 1600 1601const size_t smem = pipeline .smem ; 1602 1603ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1604ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1605ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 1606if (op -> src [1 ]) { 1607ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 1608 }else { 1609ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),2 ); 1610 } 1611if (op -> src [2 ]) { 1612ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),3 ); 1613 }else { 1614ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),3 ); 1615 } 1616ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),4 ); 1617 1618ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 1619 1620ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 1621 1622return 1 ; 1623} 1624 1625int ggml_metal_op_ssm_conv (ggml_metal_op_t ctx ,int idx ) { 1626ggml_tensor * op = ctx -> node (idx ); 1627 1628ggml_metal_library_t lib = ctx -> lib ; 1629ggml_metal_encoder_t enc = ctx -> enc ; 1630 1631GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1632GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1633GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1634GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 1635GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1636GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1637 1638ggml_metal_kargs_ssm_conv args = { 1639/*.ne00 =*/ ne00 , 1640/*.ne01 =*/ ne01 , 1641/*.ne02 =*/ ne02 , 1642/*.nb00 =*/ nb00 , 1643/*.nb01 =*/ nb01 , 1644/*.nb02 =*/ nb02 , 1645/*.ne10 =*/ ne10 , 1646/*.ne11 =*/ ne11 , 1647/*.nb10 =*/ nb10 , 1648/*.nb11 =*/ nb11 , 1649/*.ne0 =*/ ne0 , 1650/*.ne1 =*/ ne1 , 1651/*.ne2 =*/ ne2 , 1652/*.nb0 =*/ nb0 , 1653/*.nb1 =*/ nb1 , 1654/*.nb2 =*/ nb2 , 1655 }; 1656 1657// Use batched kernel for prefill (ne1 > 1) to reduce threadgroup dispatch overhead 1658const bool use_batched = (ne1 > 1 ); 1659 1660if (use_batched ) { 1661// Determine the smallest power of 2 that's >= ne1, but <= 256 1662int BATCH_SIZE ; 1663if (ne1 > 128 )BATCH_SIZE = 256 ; 1664else if (ne1 > 64 )BATCH_SIZE = 128 ; 1665else if (ne1 > 32 )BATCH_SIZE = 64 ; 1666else if (ne1 > 16 )BATCH_SIZE = 32 ; 1667else if (ne1 > 8 )BATCH_SIZE = 16 ; 1668else if (ne1 > 4 )BATCH_SIZE = 8 ; 1669else BATCH_SIZE = 2 ; 1670 1671auto pipeline = ggml_metal_library_get_pipeline_ssm_conv_batched (lib ,op ,BATCH_SIZE ); 1672 1673ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1674ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1675ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 1676ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 1677ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 1678 1679// Dispatch: ne01 rows, ceil(ne1/BATCH_SIZE) token batches, ne02 sequences 1680// Each threadgroup has BATCH_SIZE threads, each handling one token 1681const int n_token_batches = (ne1 + BATCH_SIZE - 1 ) /BATCH_SIZE ; 1682ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,n_token_batches ,ne02 ,BATCH_SIZE ,1 ,1 ); 1683 }else { 1684auto pipeline = ggml_metal_library_get_pipeline_ssm_conv (lib ,op ); 1685 1686ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1687ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1688ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 1689ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 1690ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 1691 1692ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne1 ,ne02 ,1 ,1 ,1 ); 1693 } 1694 1695return 1 ; 1696} 1697 1698int ggml_metal_op_ssm_scan (ggml_metal_op_t ctx ,int idx ) { 1699ggml_tensor * op = ctx -> node (idx ); 1700 1701ggml_metal_library_t lib = ctx -> lib ; 1702ggml_metal_encoder_t enc = ctx -> enc ; 1703const ggml_metal_device_props * props_dev = ggml_metal_device_get_props (ctx -> dev ); 1704 1705GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1706GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1707GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1708GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 1709GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 1710GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 1711GGML_TENSOR_LOCALS (int32_t ,ne3 ,op -> src [3 ],ne ); 1712GGML_TENSOR_LOCALS (uint64_t ,nb3 ,op -> src [3 ],nb ); 1713GGML_TENSOR_LOCALS (int32_t ,ne4 ,op -> src [4 ],ne ); 1714GGML_TENSOR_LOCALS (uint64_t ,nb4 ,op -> src [4 ],nb ); 1715GGML_TENSOR_LOCALS (int32_t ,ne5 ,op -> src [5 ],ne ); 1716GGML_TENSOR_LOCALS (uint64_t ,nb5 ,op -> src [5 ],nb ); 1717GGML_TENSOR_LOCALS (int32_t ,ne6 ,op -> src [6 ],ne ); 1718GGML_TENSOR_LOCALS (uint64_t ,nb6 ,op -> src [6 ],nb ); 1719GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1720GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1721 1722const ggml_tensor * src3 = op -> src [3 ]; 1723const ggml_tensor * src4 = op -> src [4 ]; 1724const ggml_tensor * src5 = op -> src [5 ]; 1725const ggml_tensor * src6 = op -> src [6 ]; 1726 1727GGML_ASSERT (src3 ); 1728GGML_ASSERT (src4 ); 1729GGML_ASSERT (src5 ); 1730GGML_ASSERT (src6 ); 1731 1732const int64_t d_state = ne00 ; 1733const int64_t d_inner = ne01 ; 1734const int64_t n_head = ne02 ; 1735const int64_t n_group = ne41 ; 1736const int64_t n_seq_tokens = ne12 ; 1737const int64_t n_seqs = ne13 ; 1738const int64_t K = ggml_get_op_params_i32 (op ,0 ); 1739 1740GGML_ASSERT (K >=1 ); 1741GGML_ASSERT (ggml_nelements (op -> src [1 ])+ K * d_state * d_inner * n_head * n_seqs == ggml_nelements (op )); 1742 1743ggml_metal_kargs_ssm_scan args = { 1744/*.d_state =*/ d_state , 1745/*.d_inner =*/ d_inner , 1746/*.n_head =*/ n_head , 1747/*.n_group =*/ n_group , 1748/*.n_seq_tokens =*/ n_seq_tokens , 1749/*.n_seq_tokens_total =*/ n_seq_tokens , 1750/*.token_offset =*/ 0 , 1751/*.n_seqs =*/ n_seqs , 1752/*.K =*/ K , 1753/*.s_off =*/ ggml_nelements (op -> src [1 ])* sizeof (float ), 1754/*.nb00 =*/ nb00 , 1755/*.nb01 =*/ nb01 , 1756/*.nb02 =*/ nb02 , 1757/*.nb03 =*/ nb03 , 1758/*.nb10 =*/ nb10 , 1759/*.nb11 =*/ nb11 , 1760/*.nb12 =*/ nb12 , 1761/*.ns12 =*/ nb12 /nb10 , 1762/*.nb13 =*/ nb13 , 1763/*.nb20 =*/ nb20 , 1764/*.nb21 =*/ nb21 , 1765/*.ns21 =*/ nb21 /nb20 , 1766/*.nb22 =*/ nb22 , 1767/*.ne30 =*/ ne30 , 1768/*.nb31 =*/ nb31 , 1769/*.nb41 =*/ nb41 , 1770/*.nb42 =*/ nb42 , 1771/*.ns42 =*/ nb42 /nb40 , 1772/*.nb43 =*/ nb43 , 1773/*.nb51 =*/ nb51 , 1774/*.nb52 =*/ nb52 , 1775/*.ns52 =*/ nb52 /nb50 , 1776/*.nb53 =*/ nb53 , 1777/*.nb0 =*/ nb0 , 1778 }; 1779 1780constexpr int64_t CHUNK = OP_SSM_SCAN_SSD_CS ; 1781 1782const int64_t snap_reserve = K > 1 ?K :0 ;// tokens reserved for sequential kernel rollback snapshots 1783const int64_t mma_tokens = ((n_seq_tokens - snap_reserve ) /CHUNK )* CHUNK ;// largest multiple of CHUNK that leaves snap_reserve for the tail 1784const bool use_mma = 1785mma_tokens > 0 && 1786ne30 == 1 && // checks that A tensor is set to scalar decay per head (A shape {1, n_head}) 1787props_dev -> has_simdgroup_mm && // hardware check for M1 or newer 1788d_state %8 == 0 && // d_state must be multiple of 8 to align with simdgroup_float 8x8 tiles 1789d_inner == OP_SSM_SCAN_SSD_HD ;// mma kernel is specialized for the Mamba-2 head dim; this checks it 1790 1791const auto dispatch = [& ](ggml_metal_pipeline_with_params pipeline ,int64_t nth ,int64_t n_tg_x ) { 1792GGML_ASSERT (nth <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 1793GGML_ASSERT (pipeline .smem <=props_dev -> max_theadgroup_memory_size ); 1794 1795ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1796ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 1797ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 1798ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 1799ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),3 ); 1800ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [3 ]),4 ); 1801ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [4 ]),5 ); 1802ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [5 ]),6 ); 1803ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [6 ]),7 ); 1804ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),8 ); 1805ggml_metal_encoder_set_threadgroup_memory_size (enc ,pipeline .smem ,0 ); 1806ggml_metal_encoder_dispatch_threadgroups (enc ,n_tg_x ,n_head ,n_seqs ,nth ,1 ,1 ); 1807 }; 1808 1809if (!use_mma ) { 1810dispatch (ggml_metal_library_get_pipeline_ssm_scan (lib ,op , false),d_state ,d_inner ); 1811return 1 ; 1812 } 1813 1814args .n_seq_tokens = mma_tokens ; 1815dispatch ( 1816ggml_metal_library_get_pipeline_ssm_scan_ssd_mma (lib ,op ), 1817OP_SSM_SCAN_SSD_NSG * 32 , 18181 ); 1819 1820if (mma_tokens < n_seq_tokens ) { 1821ggml_metal_op_concurrency_reset (ctx ); 1822 1823args .n_seq_tokens = n_seq_tokens - mma_tokens ; 1824args .token_offset = mma_tokens ; 1825dispatch (ggml_metal_library_get_pipeline_ssm_scan (lib ,op , true),d_state ,d_inner ); 1826 } 1827 1828return 1 ; 1829} 1830 1831int ggml_metal_op_rwkv (ggml_metal_op_t ctx ,int idx ) { 1832ggml_tensor * op = ctx -> node (idx ); 1833 1834ggml_metal_library_t lib = ctx -> lib ; 1835ggml_metal_encoder_t enc = ctx -> enc ; 1836 1837GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1838GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1839GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1840GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1841 1842const int64_t B = op -> op == GGML_OP_RWKV_WKV6 ?op -> src [5 ]-> ne [1 ] :op -> src [6 ]-> ne [1 ]; 1843const int64_t T = op -> src [0 ]-> ne [2 ]; 1844const int64_t C = op -> ne [0 ]; 1845const int64_t H = op -> src [0 ]-> ne [1 ]; 1846 1847auto pipeline = ggml_metal_library_get_pipeline_rwkv (lib ,op ); 1848 1849int ida = 0 ; 1850 1851ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1852ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),ida ++ ); 1853ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),ida ++ ); 1854ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),ida ++ ); 1855ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [3 ]),ida ++ ); 1856ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [4 ]),ida ++ ); 1857ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [5 ]),ida ++ ); 1858if (op -> op == GGML_OP_RWKV_WKV7 ) { 1859ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [6 ]),ida ++ ); 1860 } 1861ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),ida ++ ); 1862ggml_metal_encoder_set_bytes (enc , (void * )& B ,sizeof (B ),ida ++ ); 1863ggml_metal_encoder_set_bytes (enc , (void * )& T ,sizeof (T ),ida ++ ); 1864ggml_metal_encoder_set_bytes (enc , (void * )& C ,sizeof (C ),ida ++ ); 1865ggml_metal_encoder_set_bytes (enc , (void * )& H ,sizeof (H ),ida ++ ); 1866 1867ggml_metal_encoder_dispatch_threadgroups (enc ,B * H ,1 ,1 ,C /H ,1 ,1 ); 1868 1869return 1 ; 1870} 1871 1872int ggml_metal_op_gated_delta_net (ggml_metal_op_t ctx ,int idx ) { 1873ggml_tensor * op = ctx -> node (idx ); 1874 1875ggml_metal_library_t lib = ctx -> lib ; 1876ggml_metal_encoder_t enc = ctx -> enc ; 1877 1878const bool use_fusion = ctx -> use_fusion (); 1879const int debug_fusion = ggml_metal_fusion_info_debug (ctx -> finfo ); 1880 1881GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1882GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1883GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1884GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 1885GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 1886GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 1887GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1888GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1889 1890auto pipeline = ggml_metal_library_get_pipeline_gated_delta_net (lib ,op ); 1891 1892// when fused with the trailing cache cpy, the snapshots are written straight into the 1893// recurrent cache and the cpy is skipped (see GGML_METAL_FUSION_GDN_CACHE) 1894ggml_metal_buffer_id bid_out = ggml_metal_get_buffer_id (op ); 1895uint64_t nb_out = 0 ; 1896int n_fuse = 1 ; 1897 1898if (use_fusion ) { 1899int n = 1 ; 1900const ggml_metal_fusion * fusion = ctx -> can_fuse (idx ,GGML_METAL_FUSION_FULL ,& n ); 1901 1902if (fusion && fusion -> id == GGML_METAL_FUSION_GDN_CACHE ) { 1903const ggml_tensor * dst_cache = ctx -> node (idx + 1 )-> src [1 ];// cache view 1904 1905bid_out = ggml_metal_get_buffer_id (dst_cache ); 1906nb_out = dst_cache -> nb [2 ]/sizeof (float ); 1907n_fuse = 2 ; 1908 1909ctx -> count_fusions (fusion ); 1910 1911if (debug_fusion > 1 ) { 1912GGML_LOG_DEBUG ("%s: fuse: GATED_DELTA_NET + CPY\n" ,__func__ ); 1913 } 1914 } 1915 } 1916 1917int ida = 0 ; 1918 1919ggml_metal_kargs_gated_delta_net args = { 1920/*.ne00 =*/ ne00 , 1921/*.ne01 =*/ ne01 , 1922/*.ne02 =*/ ne02 , 1923/*.ne03 =*/ ne03 , 1924/*.nb00 =*/ nb00 , 1925/*.nb01 =*/ nb01 , 1926/*.nb02 =*/ nb02 , 1927/*.nb03 =*/ nb03 , 1928/*.ne10 =*/ ne10 , 1929/*.ne11 =*/ ne11 , 1930/*.ne12 =*/ ne12 , 1931/*.ne13 =*/ ne13 , 1932/*.nb10 =*/ nb10 , 1933/*.nb11 =*/ nb11 , 1934/*.nb12 =*/ nb12 , 1935/*.nb13 =*/ nb13 , 1936/*.ne20 =*/ ne20 , 1937/*.ne21 =*/ ne21 , 1938/*.ne22 =*/ ne22 , 1939/*.ne23 =*/ ne23 , 1940/*.nb20 =*/ nb20 , 1941/*.nb21 =*/ nb21 , 1942/*.nb22 =*/ nb22 , 1943/*.nb23 =*/ nb23 , 1944/*.ns02 =*/ (int32_t ) (nb02 /sizeof (float )), 1945/*.ns12 =*/ (int32_t ) (nb12 /sizeof (float )), 1946/*.ns22 =*/ (int32_t ) (nb22 /sizeof (float )), 1947/*.ne0 =*/ ne0 , 1948/*.ne1 =*/ ne1 , 1949/*.ne2 =*/ ne2 , 1950/*.ne3 =*/ ne3 , 1951/*.nb0 =*/ nb0 , 1952/*.nb1 =*/ nb1 , 1953/*.nb2 =*/ nb2 , 1954/*.nb3 =*/ nb3 , 1955/*.nb_out =*/ nb_out , 1956 }; 1957 1958ggml_metal_encoder_set_pipeline (enc ,pipeline ); 1959ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),ida ++ );// args 1960ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),ida ++ );// q 1961ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),ida ++ );// k 1962ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),ida ++ );// v 1963ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [3 ]),ida ++ );// gate 1964ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [4 ]),ida ++ );// beta 1965ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [5 ]),ida ++ );// state 1966ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),ida ++ );// dst (attn) 1967ggml_metal_encoder_set_buffer (enc ,bid_out ,ida ++ );// state_out 1968 1969const int nsg = pipeline .nsg ; 1970 1971ggml_metal_encoder_dispatch_threadgroups (enc ,op -> src [2 ]-> ne [0 ]/nsg ,op -> src [2 ]-> ne [1 ],op -> src [2 ]-> ne [3 ],32 ,nsg ,1 ); 1972 1973return n_fuse ; 1974} 1975 1976int ggml_metal_op_solve_tri (ggml_metal_op_t ctx ,int idx ) { 1977ggml_tensor * op = ctx -> node (idx ); 1978 1979ggml_metal_library_t lib = ctx -> lib ; 1980ggml_metal_encoder_t enc = ctx -> enc ; 1981 1982GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1983GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 1984GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1985GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 1986GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 1987GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 1988 1989ggml_metal_kargs_solve_tri args = { 1990/*.ne00 =*/ ne00 , 1991/*.ne01 =*/ ne01 , 1992/*.ne02 =*/ ne02 , 1993/*.ne03 =*/ ne03 , 1994/*.nb00 =*/ nb00 , 1995/*.nb01 =*/ nb01 , 1996/*.nb02 =*/ nb02 , 1997/*.nb03 =*/ nb03 , 1998/*.ne10 =*/ ne10 , 1999/*.ne11 =*/ ne11 , 2000/*.ne12 =*/ ne12 , 2001/*.ne13 =*/ ne13 , 2002/*.nb10 =*/ nb10 , 2003/*.nb11 =*/ nb11 , 2004/*.nb12 =*/ nb12 , 2005/*.nb13 =*/ nb13 , 2006/*.ne0 =*/ ne0 , 2007/*.ne1 =*/ ne1 , 2008/*.ne2 =*/ ne2 , 2009/*.ne3 =*/ ne3 , 2010/*.nb0 =*/ nb0 , 2011/*.nb1 =*/ nb1 , 2012/*.nb2 =*/ nb2 , 2013/*.nb3 =*/ nb3 , 2014 }; 2015 2016auto pipeline = ggml_metal_library_get_pipeline_solve_tri (lib ,op ); 2017 2018ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2019ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2020ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2021ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 2022ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 2023 2024const int nsg = pipeline .nsg ; 2025 2026ggml_metal_encoder_set_threadgroup_memory_size (enc ,pipeline .smem ,0 ); 2027 2028ggml_metal_encoder_dispatch_threadgroups (enc , (ne10 + nsg - 1 )/nsg ,ne02 ,ne03 ,32 ,nsg ,1 ); 2029 2030return 1 ; 2031} 2032 2033int ggml_metal_op_set (ggml_metal_op_t ctx ,int idx ) { 2034ggml_tensor * op = ctx -> node (idx ); 2035 2036ggml_metal_library_t lib = ctx -> lib ; 2037ggml_metal_encoder_t enc = ctx -> enc ; 2038 2039GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2040GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2041GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 2042GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 2043GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 2044GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 2045 2046ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 2047ggml_metal_buffer_id bid_src1 = ggml_metal_get_buffer_id (op -> src [1 ]); 2048ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 2049 2050const size_t pnb1 = ((const int32_t * )op -> op_params )[0 ]; 2051const size_t pnb2 = ((const int32_t * )op -> op_params )[1 ]; 2052const size_t pnb3 = ((const int32_t * )op -> op_params )[2 ]; 2053const size_t offs = ((const int32_t * )op -> op_params )[3 ]; 2054 2055const bool inplace = (bool ) ((const int32_t * )op -> op_params )[4 ]; 2056 2057if (!inplace ) { 2058// run a separate kernel to cpy src->dst 2059// not sure how to avoid this 2060// TODO: make a simpler cpy_bytes kernel 2061 2062//const id<MTLComputePipelineState> pipeline = ctx->pipelines[GGML_METAL_PIPELINE_TYPE_CPY_F32_F32].obj; 2063auto pipeline = ggml_metal_library_get_pipeline_cpy (lib ,op -> src [0 ]-> type ,op -> type ); 2064 2065ggml_metal_kargs_cpy args = { 2066/*.nk0 =*/ ne00 , 2067/*.ne00 =*/ ne00 , 2068/*.ne01 =*/ ne01 , 2069/*.ne02 =*/ ne02 , 2070/*.ne03 =*/ ne03 , 2071/*.nb00 =*/ nb00 , 2072/*.nb01 =*/ nb01 , 2073/*.nb02 =*/ nb02 , 2074/*.nb03 =*/ nb03 , 2075/*.ne0 =*/ ne0 , 2076/*.ne1 =*/ ne1 , 2077/*.ne2 =*/ ne2 , 2078/*.ne3 =*/ ne3 , 2079/*.nb0 =*/ nb0 , 2080/*.nb1 =*/ nb1 , 2081/*.nb2 =*/ nb2 , 2082/*.nb3 =*/ nb3 , 2083 }; 2084 2085ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2086ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2087ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 2088ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 2089 2090const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne00 ); 2091 2092ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 2093 2094ggml_metal_op_concurrency_reset (ctx ); 2095 } 2096 2097auto pipeline = ggml_metal_library_get_pipeline_cpy (lib ,op -> src [1 ]-> type ,op -> type ); 2098 2099GGML_ASSERT (ne10 %ggml_blck_size (op -> src [1 ]-> type )== 0 ); 2100 2101int64_t nk0 = ne10 ; 2102if (ggml_is_quantized (op -> src [1 ]-> type )) { 2103nk0 = ne10 /16 ; 2104 }else if (ggml_is_quantized (op -> type )) { 2105nk0 = ne10 /ggml_blck_size (op -> type ); 2106 } 2107 2108int nth = std::min < int > (nk0 * ne11 ,256 ); 2109 2110// when rows are small, we can batch them together in a single threadgroup 2111int nrptg = 1 ; 2112 2113// TODO: relax this constraint in the future 2114if (ggml_blck_size (op -> src [1 ]-> type )== 1 && ggml_blck_size (op -> type )== 1 ) { 2115if (nth > nk0 ) { 2116nrptg = (nth + nk0 - 1 )/nk0 ; 2117nth = nk0 ; 2118 2119if (nrptg * nth > 256 ) { 2120nrptg -- ; 2121 } 2122 } 2123 } 2124 2125nth = std::min < int > (nth ,nk0 ); 2126 2127ggml_metal_kargs_cpy args = { 2128/*.nk0 =*/ nk0 , 2129/*.ne00 =*/ ne10 , 2130/*.ne01 =*/ ne11 , 2131/*.ne02 =*/ ne12 , 2132/*.ne03 =*/ ne13 , 2133/*.nb00 =*/ nb10 , 2134/*.nb01 =*/ nb11 , 2135/*.nb02 =*/ nb12 , 2136/*.nb03 =*/ nb13 , 2137/*.ne0 =*/ ne10 , 2138/*.ne1 =*/ ne11 , 2139/*.ne2 =*/ ne12 , 2140/*.ne3 =*/ ne13 , 2141/*.nb0 =*/ ggml_element_size (op ), 2142/*.nb1 =*/ pnb1 , 2143/*.nb2 =*/ pnb2 , 2144/*.nb3 =*/ pnb3 , 2145 }; 2146 2147const int nw0 = nrptg == 1 ? (nk0 + nth - 1 )/nth :1 ; 2148 2149bid_dst .offs += offs ; 2150 2151ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2152ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2153ggml_metal_encoder_set_buffer (enc ,bid_src1 ,1 ); 2154ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 2155 2156ggml_metal_encoder_dispatch_threadgroups (enc ,nw0 * (ne11 + nrptg - 1 )/nrptg ,ne12 ,ne13 ,nth ,nrptg ,1 ); 2157 2158return 1 ; 2159} 2160 2161int ggml_metal_op_cpy (ggml_metal_op_t ctx ,int idx ) { 2162ggml_tensor * op = ctx -> node (idx ); 2163 2164ggml_metal_library_t lib = ctx -> lib ; 2165ggml_metal_encoder_t enc = ctx -> enc ; 2166 2167GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2168GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2169GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 2170GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 2171 2172auto pipeline = ggml_metal_library_get_pipeline_cpy (lib ,op -> src [0 ]-> type ,op -> type ); 2173 2174GGML_ASSERT (ne00 %ggml_blck_size (op -> src [0 ]-> type )== 0 ); 2175 2176int64_t nk0 = ne00 ; 2177if (ggml_is_quantized (op -> src [0 ]-> type )) { 2178nk0 = ne00 /16 ; 2179 }else if (ggml_is_quantized (op -> type )) { 2180nk0 = ne00 /ggml_blck_size (op -> type ); 2181 } 2182 2183int nth = std::min < int > (nk0 * ne01 ,256 ); 2184 2185// when rows are small, we can batch them together in a single threadgroup 2186int nrptg = 1 ; 2187 2188// TODO: relax this constraint in the future 2189if (ggml_blck_size (op -> src [0 ]-> type )== 1 && ggml_blck_size (op -> type )== 1 ) { 2190if (nth > nk0 ) { 2191nrptg = (nth + nk0 - 1 )/nk0 ; 2192nth = nk0 ; 2193 2194if (nrptg * nth > 256 ) { 2195nrptg -- ; 2196 } 2197 } 2198 } 2199 2200nth = std::min < int > (nth ,nk0 ); 2201 2202ggml_metal_kargs_cpy args = { 2203/*.nk0 =*/ nk0 , 2204/*.ne00 =*/ ne00 , 2205/*.ne01 =*/ ne01 , 2206/*.ne02 =*/ ne02 , 2207/*.ne03 =*/ ne03 , 2208/*.nb00 =*/ nb00 , 2209/*.nb01 =*/ nb01 , 2210/*.nb02 =*/ nb02 , 2211/*.nb03 =*/ nb03 , 2212/*.ne0 =*/ ne0 , 2213/*.ne1 =*/ ne1 , 2214/*.ne2 =*/ ne2 , 2215/*.ne3 =*/ ne3 , 2216/*.nb0 =*/ nb0 , 2217/*.nb1 =*/ nb1 , 2218/*.nb2 =*/ nb2 , 2219/*.nb3 =*/ nb3 , 2220 }; 2221 2222const int nw0 = nrptg == 1 ? (nk0 + nth - 1 )/nth :1 ; 2223 2224ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2225ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2226ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2227ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 2228 2229ggml_metal_encoder_dispatch_threadgroups (enc ,nw0 * (ne01 + nrptg - 1 )/nrptg ,ne02 ,ne03 ,nth ,nrptg ,1 ); 2230 2231return 1 ; 2232} 2233 2234int ggml_metal_op_pool_1d (ggml_metal_op_t ctx ,int idx ) { 2235ggml_tensor * op = ctx -> node (idx ); 2236 2237ggml_metal_library_t lib = ctx -> lib ; 2238ggml_metal_encoder_t enc = ctx -> enc ; 2239 2240GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2241GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2242GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 2243GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 2244 2245const int32_t * opts = op -> op_params ; 2246ggml_op_pool op_pool = (ggml_op_pool )opts [0 ]; 2247 2248const int32_t k0 = opts [1 ]; 2249const int32_t s0 = opts [2 ]; 2250const int32_t p0 = opts [3 ]; 2251 2252const int64_t IW = op -> src [0 ]-> ne [0 ]; 2253const int64_t OW = op -> ne [0 ]; 2254 2255const int64_t np = ggml_nelements (op ); 2256 2257ggml_metal_kargs_pool_1d args_pool_1d = { 2258/* .k0 = */ k0 , 2259/* .s0 = */ s0 , 2260/* .p0 = */ p0 , 2261/* .IW = */ IW , 2262/* .OW = */ OW , 2263/* .np = */ np 2264 }; 2265 2266auto pipeline = ggml_metal_library_get_pipeline_pool_1d (lib ,op ,op_pool ); 2267 2268const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ), (int )np ); 2269const int ntg = (np + nth - 1 ) /nth ; 2270 2271ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2272ggml_metal_encoder_set_bytes (enc ,& args_pool_1d ,sizeof (args_pool_1d ),0 ); 2273ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2274ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 2275 2276ggml_metal_encoder_dispatch_threadgroups (enc ,ntg ,1 ,1 ,nth ,1 ,1 ); 2277 2278return 1 ; 2279} 2280 2281// supported FWHT sizes, must stay in sync with the 2282// kernel_fwht_f32_<N> templates in ggml-metal.metal 2283static bool ggml_metal_fwht_supported_size (int64_t n ) { 2284return n == 64 || n == 128 || n == 256 || n == 512 ; 2285} 2286 2287int ggml_metal_op_fwht (ggml_metal_op_t ctx ,int idx ) { 2288ggml_tensor * op = ctx -> node (idx ); 2289 2290ggml_metal_library_t lib = ctx -> lib ; 2291ggml_metal_encoder_t enc = ctx -> enc ; 2292 2293ggml_tensor * src1 = op -> src [1 ]; 2294 2295const int64_t n = src1 -> ne [0 ]; 2296const int64_t nrows = ggml_nrows (src1 ); 2297 2298ggml_metal_kargs_fwht args = { 2299/*.nrows = */ (int32_t )nrows , 2300 }; 2301 2302auto pipeline = ggml_metal_library_get_pipeline_fwht (lib ,n ); 2303 2304ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2305ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2306ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (src1 ),1 ); 2307ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 2308 2309const int th_max = ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ); 2310const int simd_size = 32 ; 2311 2312int sg_per_tg = 2 ; 2313sg_per_tg = std::min (sg_per_tg ,th_max /simd_size ); 2314sg_per_tg = std::max (sg_per_tg ,1 ); 2315 2316const int64_t n_tg = (nrows + sg_per_tg - 1 ) /sg_per_tg ; 2317ggml_metal_encoder_dispatch_threadgroups (enc ,n_tg ,1 ,1 ,32 * sg_per_tg ,1 ,1 ); 2318 2319return 1 ; 2320} 2321 2322int ggml_metal_op_pool_2d (ggml_metal_op_t ctx ,int idx ) { 2323ggml_tensor * op = ctx -> node (idx ); 2324 2325ggml_metal_library_t lib = ctx -> lib ; 2326ggml_metal_encoder_t enc = ctx -> enc ; 2327 2328GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2329GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2330GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 2331GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 2332 2333const int32_t * opts = op -> op_params ; 2334ggml_op_pool op_pool = (ggml_op_pool )opts [0 ]; 2335 2336const int32_t k0 = opts [1 ]; 2337const int32_t k1 = opts [2 ]; 2338const int32_t s0 = opts [3 ]; 2339const int32_t s1 = opts [4 ]; 2340const int32_t p0 = opts [5 ]; 2341const int32_t p1 = opts [6 ]; 2342 2343const int64_t IH = op -> src [0 ]-> ne [1 ]; 2344const int64_t IW = op -> src [0 ]-> ne [0 ]; 2345 2346const int64_t N = op -> ne [3 ]; 2347const int64_t OC = op -> ne [2 ]; 2348const int64_t OH = op -> ne [1 ]; 2349const int64_t OW = op -> ne [0 ]; 2350 2351const int64_t np = N * OC * OH * OW ; 2352 2353ggml_metal_kargs_pool_2d args_pool_2d = { 2354/* .k0 = */ k0 , 2355/* .k1 = */ k1 , 2356/* .s0 = */ s0 , 2357/* .s1 = */ s1 , 2358/* .p0 = */ p0 , 2359/* .p1 = */ p1 , 2360/* .IH = */ IH , 2361/* .IW = */ IW , 2362/* .OH = */ OH , 2363/* .OW = */ OW , 2364/* .np = */ np 2365 }; 2366 2367auto pipeline = ggml_metal_library_get_pipeline_pool_2d (lib ,op ,op_pool ); 2368 2369const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ), (int )np ); 2370const int ntg = (np + nth - 1 ) /nth ; 2371 2372ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2373ggml_metal_encoder_set_bytes (enc ,& args_pool_2d ,sizeof (args_pool_2d ),0 ); 2374ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2375ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 2376 2377ggml_metal_encoder_dispatch_threadgroups (enc ,ntg ,1 ,1 ,nth ,1 ,1 ); 2378 2379return 1 ; 2380} 2381 2382int ggml_metal_op_mul_mat (ggml_metal_op_t ctx ,int idx ) { 2383ggml_tensor * op = ctx -> node (idx ); 2384 2385ggml_metal_library_t lib = ctx -> lib ; 2386ggml_metal_encoder_t enc = ctx -> enc ; 2387 2388const int32_t hint = ggml_get_op_params_i32 (op ,1 ); 2389 2390if (hint == GGML_HINT_SRC0_IS_HADAMARD ) { 2391if (op -> src [1 ]-> type == GGML_TYPE_F32 && 2392op -> type == GGML_TYPE_F32 && 2393ggml_is_contiguous (op -> src [1 ])&& 2394ggml_is_contiguous (op )&& 2395ggml_are_same_shape (op -> src [1 ],op )&& 2396ggml_metal_fwht_supported_size (op -> src [1 ]-> ne [0 ])) { 2397return ggml_metal_op_fwht (ctx ,idx ); 2398 } 2399 } 2400const ggml_metal_device_props * props_dev = ggml_metal_device_get_props (ctx -> dev ); 2401 2402GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2403GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2404GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 2405GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 2406GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 2407GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 2408 2409GGML_ASSERT (ne00 == ne10 ); 2410 2411GGML_ASSERT (ne12 %ne02 == 0 ); 2412GGML_ASSERT (ne13 %ne03 == 0 ); 2413 2414const int16_t r2 = ne12 /ne02 ; 2415const int16_t r3 = ne13 /ne03 ; 2416 2417// first try to use small-batch mat-mv kernels 2418// these should be efficient for BS [2, ~8] 2419if (op -> src [1 ]-> type == GGML_TYPE_F32 && (ne00 %128 == 0 )&& 2420 ( 2421 ( 2422 ( 2423op -> src [0 ]-> type == GGML_TYPE_F32 || // TODO: helper function 2424op -> src [0 ]-> type == GGML_TYPE_F16 || 2425op -> src [0 ]-> type == GGML_TYPE_BF16 || 2426op -> src [0 ]-> type == GGML_TYPE_Q1_0 || 2427op -> src [0 ]-> type == GGML_TYPE_Q2_0 || 2428op -> src [0 ]-> type == GGML_TYPE_Q4_0 || 2429op -> src [0 ]-> type == GGML_TYPE_Q4_1 || 2430op -> src [0 ]-> type == GGML_TYPE_Q5_0 || 2431op -> src [0 ]-> type == GGML_TYPE_Q5_1 || 2432op -> src [0 ]-> type == GGML_TYPE_Q8_0 || 2433op -> src [0 ]-> type == GGML_TYPE_MXFP4 || 2434op -> src [0 ]-> type == GGML_TYPE_IQ4_NL || 2435 false)&& (ne11 >=2 && ne11 <=8 ) 2436 )|| 2437 ( 2438 ( 2439op -> src [0 ]-> type == GGML_TYPE_Q4_K || 2440op -> src [0 ]-> type == GGML_TYPE_Q5_K || 2441op -> src [0 ]-> type == GGML_TYPE_Q6_K || 2442op -> src [0 ]-> type == GGML_TYPE_Q2_K || 2443op -> src [0 ]-> type == GGML_TYPE_Q3_K || 2444 false)&& (ne11 >=4 && ne11 <=8 ) 2445 ) 2446 ) 2447 ) { 2448// TODO: determine the optimal parameters based on grid utilization 2449// I still don't know why we should not always use the maximum available threads: 2450// 2451// nsg = pipeline.maxTotalThreadsPerThreadgroup / 32 2452// 2453// my current hypothesis is that the work grid is not evenly divisible for different nsg 2454// values and there can be some tail effects when nsg is high. need to confirm this 2455// 2456const int nsg = 2 ;// num simdgroups per threadgroup 2457 2458// num threads along row per simdgroup 2459int16_t nxpsg = 0 ; 2460if (ne00 %256 == 0 && ne11 < 3 ) { 2461nxpsg = 16 ; 2462 }else if (ne00 %128 == 0 ) { 2463nxpsg = 8 ; 2464 }else { 2465nxpsg = 4 ; 2466 } 2467 2468const int16_t nypsg = 32 /nxpsg ;// num threads along col per simdgroup (i.e. a simdgroup processes that many src0 rows at a time) 2469const int16_t r0ptg = nypsg * nsg ;// num src0 rows per threadgroup 2470int16_t r1ptg = 4 ;// num src1 rows per threadgroup 2471 2472// note: not sure how optimal are those across all different hardware. there might be something cleverer 2473switch (ne11 ) { 2474case 2 : 2475r1ptg = 2 ;break ; 2476case 3 : 2477case 6 : 2478r1ptg = 3 ;break ; 2479case 4 : 2480case 7 : 2481case 8 : 2482r1ptg = 4 ;break ; 2483case 5 : 2484r1ptg = 5 ;break ; 2485default : 2486GGML_ABORT ("unsupported ne11" ); 2487 }; 2488 2489auto pipeline = ggml_metal_library_get_pipeline_mul_mv_ext (lib ,op ,nsg ,nxpsg ,r1ptg ); 2490 2491ggml_metal_kargs_mul_mv_ext args = { 2492/*.ne00 =*/ ne00 , 2493/*.ne01 =*/ ne01 , 2494/*.ne02 =*/ ne02 , 2495/*.nb00 =*/ nb00 , 2496/*.nb01 =*/ nb01 , 2497/*.nb02 =*/ nb02 , 2498/*.nb03 =*/ nb03 , 2499/*.ne10 =*/ ne10 , 2500/*.ne11 =*/ ne11 , 2501/*.ne12 =*/ ne12 , 2502/*.nb10 =*/ nb10 , 2503/*.nb11 =*/ nb11 , 2504/*.nb12 =*/ nb12 , 2505/*.nb13 =*/ nb13 , 2506/*.ne0 =*/ ne0 , 2507/*.ne1 =*/ ne1 , 2508/*.r2 =*/ r2 , 2509/*.r3 =*/ r3 , 2510 }; 2511 2512ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2513ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2514ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2515ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 2516ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 2517 2518ggml_metal_encoder_dispatch_threadgroups (enc , ((ne01 + r0ptg - 1 )/r0ptg ), ((ne11 + r1ptg - 1 )/r1ptg ),ne12 * ne13 ,32 ,nsg ,1 ); 2519 }else if (ggml_metal_op_mul_mat_use_mm (op ,props_dev -> has_simdgroup_mm )) { 2520//GGML_LOG_INFO("matrix: ne00 = %6d, ne01 = %6d, ne02 = %6d, ne11 = %6d, ne12 = %6d\n", ne00, ne01, ne02, ne11, ne12); 2521 2522// some Metal matrix data types require aligned pointers 2523// ref: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf (Table 2.5) 2524//switch (op->src[0]->type) { 2525// case GGML_TYPE_F32: GGML_ASSERT(nb01 % 16 == 0); break; 2526// case GGML_TYPE_F16: GGML_ASSERT(nb01 % 8 == 0); break; 2527// case GGML_TYPE_BF16: GGML_ASSERT(nb01 % 8 == 0); break; 2528// default: break; 2529//} 2530 2531auto pipeline = ggml_metal_library_get_pipeline_mul_mm (lib ,op ); 2532 2533ggml_metal_kargs_mul_mm args = { 2534/*.ne00 =*/ ne00 , 2535/*.ne02 =*/ ne02 , 2536/*.nb01 =*/ nb01 , 2537/*.nb02 =*/ nb02 , 2538/*.nb03 =*/ nb03 , 2539/*.ne12 =*/ ne12 , 2540/*.nb10 =*/ nb10 , 2541/*.nb11 =*/ nb11 , 2542/*.nb12 =*/ nb12 , 2543/*.nb13 =*/ nb13 , 2544/*.ne0 =*/ ne0 , 2545/*.ne1 =*/ ne1 , 2546/*.r2 =*/ r2 , 2547/*.r3 =*/ r3 , 2548 }; 2549 2550ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2551ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2552ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2553ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 2554ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 2555 2556const size_t smem = pipeline .smem ; 2557 2558ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 2559 2560const int nr0 = pipeline .nr0 ; 2561const int nr1 = pipeline .nr1 ; 2562const int nsg = pipeline .nsg ; 2563 2564ggml_metal_encoder_dispatch_threadgroups (enc , ((ne11 + nr1 - 1 ) /nr1 ), ((ne01 + nr0 - 1 ) /nr0 ),ne12 * ne13 ,32 ,nsg ,1 ); 2565 }else { 2566auto pipeline = ggml_metal_library_get_pipeline_mul_mv (lib ,op ); 2567 2568const int nr0 = pipeline .nr0 ; 2569const int nr1 = pipeline .nr1 ; 2570const int nsg = pipeline .nsg ; 2571 2572const size_t smem = pipeline .smem ; 2573 2574ggml_metal_kargs_mul_mv args = { 2575/*.ne00 =*/ ne00 , 2576/*.ne01 =*/ ne01 , 2577/*.ne02 =*/ ne02 , 2578/*.nb00 =*/ nb00 , 2579/*.nb01 =*/ nb01 , 2580/*.nb02 =*/ nb02 , 2581/*.nb03 =*/ nb03 , 2582/*.ne10 =*/ ne10 , 2583/*.ne11 =*/ ne11 , 2584/*.ne12 =*/ ne12 , 2585/*.nb10 =*/ nb10 , 2586/*.nb11 =*/ nb11 , 2587/*.nb12 =*/ nb12 , 2588/*.nb13 =*/ nb13 , 2589/*.ne0 =*/ ne0 , 2590/*.ne1 =*/ ne1 , 2591/*.nr0 =*/ nr0 , 2592/*.r2 =*/ r2 , 2593/*.r3 =*/ r3 , 2594 }; 2595 2596ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2597ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2598ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2599ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 2600ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 2601 2602ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 2603 2604if (op -> src [0 ]-> type == GGML_TYPE_F32 || 2605op -> src [0 ]-> type == GGML_TYPE_F16 || 2606op -> src [0 ]-> type == GGML_TYPE_BF16 || 2607op -> src [0 ]-> type == GGML_TYPE_Q8_0 ) { 2608ggml_metal_encoder_dispatch_threadgroups (enc , ((ne01 + nr0 - 1 )/(nr0 )), ((ne11 + nr1 - 1 )/nr1 ),ne12 * ne13 ,32 ,nsg ,1 ); 2609 }else { 2610ggml_metal_encoder_dispatch_threadgroups (enc , ((ne01 + nr0 * nsg - 1 )/(nr0 * nsg )), ((ne11 + nr1 - 1 )/nr1 ),ne12 * ne13 ,32 ,nsg ,1 ); 2611 } 2612 } 2613 2614return 1 ; 2615} 2616 2617size_t ggml_metal_op_mul_mat_id_extra_tpe (const ggml_tensor * op ) { 2618assert (op -> op == GGML_OP_MUL_MAT_ID ); 2619 2620const int64_t ne02 = op -> src [0 ]-> ne [2 ];// n_expert 2621 2622return ggml_type_size (GGML_TYPE_I32 )* ne02 ; 2623} 2624 2625size_t ggml_metal_op_mul_mat_id_extra_ids (const ggml_tensor * op ) { 2626assert (op -> op == GGML_OP_MUL_MAT_ID ); 2627 2628const int64_t ne02 = op -> src [0 ]-> ne [2 ];// n_expert 2629const int64_t ne21 = op -> src [2 ]-> ne [1 ];// n_token 2630 2631return ggml_type_size (GGML_TYPE_I32 )* ne02 * ne21 ; 2632} 2633 2634int ggml_metal_op_mul_mat_id (ggml_metal_op_t ctx ,int idx ) { 2635ggml_tensor * op = ctx -> node (idx ); 2636 2637ggml_metal_library_t lib = ctx -> lib ; 2638ggml_metal_encoder_t enc = ctx -> enc ; 2639 2640const ggml_metal_device_props * props_dev = ggml_metal_device_get_props (ctx -> dev ); 2641 2642GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2643GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2644GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 2645GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 2646GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 2647GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 2648GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 2649GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 2650 2651// src2 = ids 2652GGML_ASSERT (op -> src [2 ]-> type == GGML_TYPE_I32 ); 2653 2654GGML_ASSERT (!ggml_is_transposed (op -> src [0 ])); 2655GGML_ASSERT (!ggml_is_transposed (op -> src [1 ])); 2656 2657GGML_ASSERT (ne03 == 1 ); 2658GGML_ASSERT (ne13 == 1 ); 2659 2660ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 2661ggml_metal_buffer_id bid_src1 = ggml_metal_get_buffer_id (op -> src [1 ]); 2662ggml_metal_buffer_id bid_src2 = ggml_metal_get_buffer_id (op -> src [2 ]); 2663ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 2664 2665const uint32_t r2 = 1 ; 2666const uint32_t r3 = 1 ; 2667 2668if (ggml_metal_op_mul_mat_id_use_mm (op ,props_dev -> has_simdgroup_mm )) { 2669// some Metal matrix data types require aligned pointers 2670// ref: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf (Table 2.5) 2671//switch (op->src[0]->type) { 2672// case GGML_TYPE_F32: GGML_ASSERT(nb01 % 16 == 0); break; 2673// case GGML_TYPE_F16: GGML_ASSERT(nb01 % 8 == 0); break; 2674// case GGML_TYPE_BF16: GGML_ASSERT(nb01 % 8 == 0); break; 2675// default: break; 2676//} 2677 2678// extra buffers for intermediate id mapping 2679ggml_metal_buffer_id bid_tpe = bid_dst ; 2680bid_tpe .offs += ggml_nbytes (op ); 2681 2682ggml_metal_buffer_id bid_ids = bid_tpe ; 2683bid_ids .offs += ggml_metal_op_mul_mat_id_extra_tpe (op ); 2684 2685 { 2686ggml_metal_kargs_mul_mm_id_map0 args = { 2687ne02 , 2688ne10 , 2689ne11 ,// n_expert_used (bcast) 2690nb11 , 2691nb12 , 2692ne21 ,// n_tokens 2693ne20 ,// n_expert_used 2694nb21 , 2695 }; 2696 2697auto pipeline = ggml_metal_library_get_pipeline_mul_mm_id_map0 (lib ,ne02 ,ne20 ); 2698 2699const size_t smem = pipeline .smem ; 2700 2701GGML_ASSERT (ne02 <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 2702 2703GGML_ASSERT (smem <=props_dev -> max_theadgroup_memory_size ); 2704 2705ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2706ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2707ggml_metal_encoder_set_buffer (enc ,bid_src2 ,1 ); 2708ggml_metal_encoder_set_buffer (enc ,bid_tpe ,2 ); 2709ggml_metal_encoder_set_buffer (enc ,bid_ids ,3 ); 2710 2711ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 2712 2713ggml_metal_encoder_dispatch_threadgroups (enc ,1 ,1 ,1 ,ne02 ,1 ,1 ); 2714 } 2715 2716// this barrier is always needed because the next kernel has to wait for the id maps to be computed 2717ggml_metal_op_concurrency_reset (ctx ); 2718 2719 { 2720auto pipeline = ggml_metal_library_get_pipeline_mul_mm_id (lib ,op ); 2721 2722ggml_metal_kargs_mul_mm_id args = { 2723/*.ne00 =*/ ne00 , 2724/*.ne02 =*/ ne02 , 2725/*.nb01 =*/ nb01 , 2726/*.nb02 =*/ nb02 , 2727/*.nb03 =*/ nb03 , 2728/*.ne11 =*/ ne11 ,// n_expert_used (bcast) 2729/*.nb10 =*/ nb10 , 2730/*.nb11 =*/ nb11 , 2731/*.nb12 =*/ nb12 , 2732/*.nb13 =*/ nb13 , 2733/*.ne20 =*/ ne20 ,// n_expert_used 2734/*.ne21 =*/ ne21 ,// n_tokens 2735/*.ne0 =*/ ne0 , 2736/*.ne1 =*/ ne1 , 2737/*.r2 =*/ r2 , 2738/*.r3 =*/ r3 , 2739 }; 2740 2741ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2742ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2743ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 2744ggml_metal_encoder_set_buffer (enc ,bid_src1 ,2 ); 2745ggml_metal_encoder_set_buffer (enc ,bid_tpe ,3 ); 2746ggml_metal_encoder_set_buffer (enc ,bid_ids ,4 ); 2747ggml_metal_encoder_set_buffer (enc ,bid_dst ,5 ); 2748 2749const size_t smem = pipeline .smem ; 2750 2751ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 2752 2753ggml_metal_encoder_dispatch_threadgroups (enc , (ne21 + 31 )/32 , (ne01 + 63 )/64 ,ne02 ,128 ,1 ,1 ); 2754 } 2755 }else { 2756auto pipeline = ggml_metal_library_get_pipeline_mul_mv_id (lib ,op ); 2757 2758const int nr0 = pipeline .nr0 ; 2759const int nr1 = pipeline .nr1 ; 2760const int nsg = pipeline .nsg ; 2761 2762const size_t smem = pipeline .smem ; 2763 2764ggml_metal_kargs_mul_mv_id args = { 2765/*.nei0 =*/ ne20 , 2766/*.nei1 =*/ ne21 , 2767/*.nbi1 =*/ nb21 , 2768/*.ne00 =*/ ne00 , 2769/*.ne01 =*/ ne01 , 2770/*.ne02 =*/ ne02 , 2771/*.nb00 =*/ nb00 , 2772/*.nb01 =*/ nb01 , 2773/*.nb02 =*/ nb02 , 2774/*.ne10 =*/ ne10 , 2775/*.ne11 =*/ ne11 , 2776/*.ne12 =*/ ne12 , 2777/*.ne13 =*/ ne13 , 2778/*.nb10 =*/ nb10 , 2779/*.nb11 =*/ nb11 , 2780/*.nb12 =*/ nb12 , 2781/*.ne0 =*/ ne0 , 2782/*.ne1 =*/ ne1 , 2783/*.nb1 =*/ nb1 , 2784/*.nr0 =*/ nr0 , 2785 }; 2786 2787if (ggml_is_quantized (op -> src [0 ]-> type )) { 2788GGML_ASSERT (ne00 >=nsg * nr0 ); 2789 } 2790 2791ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2792ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2793ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 2794ggml_metal_encoder_set_buffer (enc ,bid_src1 ,2 ); 2795ggml_metal_encoder_set_buffer (enc ,bid_dst ,3 ); 2796ggml_metal_encoder_set_buffer (enc ,bid_src2 ,4 ); 2797 2798const int64_t _ne1 = 1 ; 2799const int64_t ne123 = ne20 * ne21 ; 2800 2801ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 2802 2803if (op -> src [0 ]-> type == GGML_TYPE_F32 || 2804op -> src [0 ]-> type == GGML_TYPE_F16 || 2805op -> src [0 ]-> type == GGML_TYPE_BF16 || 2806op -> src [0 ]-> type == GGML_TYPE_Q8_0 ) { 2807ggml_metal_encoder_dispatch_threadgroups (enc , (ne01 + nr0 - 1 )/(nr0 ), (_ne1 + nr1 - 1 )/nr1 ,ne123 ,32 ,nsg ,1 ); 2808 }else { 2809ggml_metal_encoder_dispatch_threadgroups (enc , (ne01 + nr0 * nsg - 1 )/(nr0 * nsg ), (_ne1 + nr1 - 1 )/nr1 ,ne123 ,32 ,nsg ,1 ); 2810 } 2811 } 2812 2813return 1 ; 2814} 2815 2816int ggml_metal_op_add_id (ggml_metal_op_t ctx ,int idx ) { 2817ggml_tensor * op = ctx -> node (idx ); 2818 2819ggml_metal_library_t lib = ctx -> lib ; 2820ggml_metal_encoder_t enc = ctx -> enc ; 2821 2822GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2823GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2824GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 2825GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 2826GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 2827GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 2828GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 2829 2830GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 ); 2831GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 2832GGML_ASSERT (op -> src [2 ]-> type == GGML_TYPE_I32 ); 2833GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 2834 2835GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 2836 2837ggml_metal_kargs_add_id args = { 2838/*.ne0 =*/ ne0 , 2839/*.ne1 =*/ ne1 , 2840/*.nb01 =*/ nb01 , 2841/*.nb02 =*/ nb02 , 2842/*.nb11 =*/ nb11 , 2843/*.nb21 =*/ nb21 , 2844 }; 2845 2846auto pipeline = ggml_metal_library_get_pipeline_base (lib ,GGML_OP_ADD_ID ); 2847 2848ggml_metal_encoder_set_pipeline (enc ,pipeline ); 2849ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 2850ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 2851ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 2852ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),3 ); 2853ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),4 ); 2854 2855const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne00 ); 2856 2857ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,1 ,nth ,1 ,1 ); 2858 2859return 1 ; 2860} 2861 2862bool ggml_metal_op_flash_attn_ext_use_vec (const ggml_tensor * op ) { 2863assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 2864 2865const int64_t ne00 = op -> src [0 ]-> ne [0 ];// head size 2866const int64_t ne01 = op -> src [0 ]-> ne [1 ];// batch size 2867 2868// use vec kernel if the batch size is small and if the head size is supported 2869return (ne01 < 20 )&& (ne00 %32 == 0 ); 2870} 2871 2872// ref: https://github.com/ggml-org/llama.cpp/pull/27390 2873// dequantize the quantized KV cache to F16 before running the F16 flash attention kernels 2874static bool ggml_metal_op_flash_attn_ext_use_kv_f16 (const ggml_tensor * op ) { 2875assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 2876 2877// depending on compute/bandwidth ratio, dequant to f16 kv is not always beneficial 2878// ref: https://github.com/ggml-org/llama.cpp/pull/27390#issuecomment-5355152767 2879// TODO: tune per device 2880if (op -> src [0 ]-> ne [1 ]< 32 ) { 2881return false; 2882 } 2883 2884switch (op -> src [1 ]-> type ) { 2885case GGML_TYPE_Q4_0 : 2886case GGML_TYPE_Q4_1 : 2887case GGML_TYPE_Q5_0 : 2888case GGML_TYPE_Q5_1 : 2889case GGML_TYPE_Q8_0 : 2890return true; 2891default : 2892return false; 2893 } 2894} 2895 2896// returns the n_kv_max hint if the sparse path is available for this op, or 0 otherwise 2897// the mask (src[3]) remains the single source of truth: finite entries are the valid KV positions, 2898// n_kv_max is only an upper bound on their number per mask row, used to size the index lists 2899static int ggml_metal_op_flash_attn_ext_n_kv_max_sparse (const ggml_tensor * op ) { 2900assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 2901 2902int32_t n_kv_max = 0 ; 2903memcpy (& n_kv_max , ((const int32_t * )op -> op_params )+ 4 ,sizeof (n_kv_max )); 2904 2905if (n_kv_max <=0 ) { 2906return 0 ; 2907 } 2908 2909// the sparse indices are gathered from the mask 2910if (!op -> src [3 ]) { 2911return 0 ; 2912 } 2913 2914// bound the size of the index lists 2915if (n_kv_max > 4096 ) { 2916return 0 ; 2917 } 2918 2919// vec kernel instantiations exist for these (type, dk, dv) combinations only 2920const int64_t dk = op -> src [1 ]-> ne [0 ]; 2921const int64_t dv = op -> src [2 ]-> ne [0 ]; 2922 2923const bool dk_dv_ok = (dk == 32 && dv == 32 )|| 2924 (dk == 64 && dv == 64 )|| 2925 (dk == 96 && dv == 96 )|| 2926 (dk == 128 && dv == 128 )|| 2927 (dk == 192 && dv == 128 )|| 2928 (dk == 192 && dv == 192 )|| 2929 (dk == 256 && dv == 256 )|| 2930 (dk == 320 && dv == 256 )|| 2931 (dk == 512 && dv == 512 )|| 2932 (dk == 576 && dv == 512 ); 2933 2934if (!dk_dv_ok ) { 2935return 0 ; 2936 } 2937 2938switch (op -> src [1 ]-> type ) { 2939case GGML_TYPE_F16 : 2940case GGML_TYPE_BF16 : 2941case GGML_TYPE_F32 : 2942case GGML_TYPE_Q4_0 : 2943case GGML_TYPE_Q4_1 : 2944case GGML_TYPE_Q5_0 : 2945case GGML_TYPE_Q5_1 : 2946case GGML_TYPE_Q8_0 : 2947break ; 2948default : 2949return 0 ; 2950 } 2951 2952return n_kv_max ; 2953} 2954 2955// in some models (e.g. MLA-based), V is a view of K (the first ne20 elements of each K row); 2956// the dequantized V is then a view of the dequantized K and does not need its own dequant or scratch 2957// - ref: https://github.com/ggml-org/llama.cpp/pull/13435 2958static bool ggml_metal_op_flash_attn_ext_v_is_view_of_k (const ggml_tensor * op ) { 2959assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 2960 2961const ggml_tensor * K = op -> src [1 ]; 2962const ggml_tensor * V = op -> src [2 ]; 2963 2964return V -> view_src && (V -> view_src == K || (V -> view_src == K -> view_src && V -> view_offs == K -> view_offs )); 2965} 2966 2967// size of the F16 dequantized K tensor; the dequantized V tensor follows it in the same scratch buffer 2968static size_t ggml_metal_op_flash_attn_ext_kv_f16_k_size (const ggml_tensor * op ) { 2969assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 2970 2971GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 2972 2973return GGML_PAD (sizeof (ggml_fp16_t )* (size_t )ne10 * ne11 * ne12 * ne13 ,16 ); 2974} 2975 2976size_t ggml_metal_op_flash_attn_ext_extra_pad (const ggml_tensor * op ) { 2977assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 2978 2979GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 2980GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 2981GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 2982GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 2983GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 2984GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 2985GGML_TENSOR_LOCALS (int32_t ,ne3 ,op -> src [3 ],ne ); 2986GGML_TENSOR_LOCALS (uint64_t ,nb3 ,op -> src [3 ],nb ); 2987 2988size_t res = 0 ; 2989 2990const bool has_mask = op -> src [3 ]!= nullptr ; 2991const bool use_kv_f16 = ggml_metal_op_flash_attn_ext_use_kv_f16 (op ); 2992 2993// when the KV is dequantized to F16, the pad kernel copies the tail chunk from the F16 scratch buffer 2994// note: when V is a view of K, the dequantized V is read from the dequantized K with K's row stride 2995const bool v_is_view_of_k = use_kv_f16 && ggml_metal_op_flash_attn_ext_v_is_view_of_k (op ); 2996uint64_t nb11_pad = nb11 ; 2997uint64_t nb21_pad = nb21 ; 2998 2999if (use_kv_f16 ) { 3000nb11_pad = sizeof (ggml_fp16_t )* ne10 ; 3001nb21_pad = sizeof (ggml_fp16_t )* (v_is_view_of_k ?ne10 :ne20 ); 3002 } 3003 3004// note: the non-vec kernel requires more extra memory, so always reserve for it 3005GGML_ASSERT (OP_FLASH_ATTN_EXT_NCPSG >=OP_FLASH_ATTN_EXT_VEC_NCPSG ); 3006 3007//if (ggml_metal_op_flash_attn_ext_use_vec(op)) { 3008if (false) { 3009// note: always reserve the padding space to avoid graph reallocations 3010//const bool has_kvpad = ne11 % OP_FLASH_ATTN_EXT_VEC_NCPSG != 0; 3011const bool has_kvpad = true; 3012 3013if (has_kvpad ) { 3014res += OP_FLASH_ATTN_EXT_VEC_NCPSG * ( 3015nb11_pad * ne12 * ne13 + 3016nb21_pad * ne22 * ne23 + 3017 (has_mask ?ggml_type_size (GGML_TYPE_F16 )* ne31 * ne32 * ne33 :0 )); 3018 } 3019 }else { 3020//const bool has_kvpad = ne11 % OP_FLASH_ATTN_EXT_NCPSG != 0; 3021const bool has_kvpad = true; 3022 3023if (has_kvpad ) { 3024res += OP_FLASH_ATTN_EXT_NCPSG * ( 3025nb11_pad * ne12 * ne13 + 3026nb21_pad * ne22 * ne23 + 3027 (has_mask ?ggml_type_size (GGML_TYPE_F16 )* ne31 * ne32 * ne33 :0 )); 3028 } 3029 } 3030 3031return res ; 3032} 3033 3034size_t ggml_metal_op_flash_attn_ext_extra_blk (const ggml_tensor * op ) { 3035assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 3036 3037GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 3038//GGML_TENSOR_LOCALS(uint64_t, nb0, op->src[0], nb); 3039//GGML_TENSOR_LOCALS( int32_t, ne1, op->src[1], ne); 3040//GGML_TENSOR_LOCALS(uint64_t, nb1, op->src[1], nb); 3041//GGML_TENSOR_LOCALS( int32_t, ne2, op->src[2], ne); 3042//GGML_TENSOR_LOCALS(uint64_t, nb2, op->src[2], nb); 3043GGML_TENSOR_LOCALS (int32_t ,ne3 ,op -> src [3 ],ne ); 3044GGML_TENSOR_LOCALS (uint64_t ,nb3 ,op -> src [3 ],nb ); 3045 3046size_t res = 0 ; 3047 3048const bool has_mask = op -> src [3 ]!= nullptr ; 3049 3050if (!has_mask ) { 3051return res ; 3052 } 3053 3054const bool is_vec = ggml_metal_op_flash_attn_ext_use_vec (op ); 3055 3056// this optimization is not useful for the vector kernels 3057// note: always reserve the blk buffer to avoid graph reallocations 3058//if (is_vec) { 3059// return res; 3060//} 3061 3062const int nqptg = is_vec ?OP_FLASH_ATTN_EXT_VEC_NQPSG :OP_FLASH_ATTN_EXT_NQPSG ; 3063const int ncpsg = is_vec ?OP_FLASH_ATTN_EXT_VEC_NCPSG :OP_FLASH_ATTN_EXT_NCPSG ; 3064 3065const int64_t ne1 = (ne01 + nqptg - 1 )/nqptg ; 3066const int64_t ne0 = (ne30 + ncpsg - 1 )/ncpsg ; 3067 3068res += GGML_PAD (ggml_type_size (GGML_TYPE_I8 )* ne0 * ne1 * ne32 * ne33 ,32 ); 3069 3070return res ; 3071} 3072 3073size_t ggml_metal_op_flash_attn_ext_extra_tmp (const ggml_tensor * op ) { 3074assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 3075 3076GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 3077GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 3078//GGML_TENSOR_LOCALS( int32_t, ne1, op->src[1], ne); 3079//GGML_TENSOR_LOCALS(uint64_t, nb1, op->src[1], nb); 3080GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 3081GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 3082//GGML_TENSOR_LOCALS( int32_t, ne3, op->src[3], ne); 3083//GGML_TENSOR_LOCALS(uint64_t, nb3, op->src[3], nb); 3084 3085size_t res = 0 ; 3086 3087// note: always reserve the temp buffer to avoid graph reallocations 3088//if (ggml_metal_op_flash_attn_ext_use_vec(op)) { 3089if (true) { 3090const int64_t nwg = 32 ; 3091const int64_t ne01_max = std::min (ne01 ,32 ); 3092 3093// temp buffer for writing the results from each workgroup 3094// - ne20: the size of the Value head 3095// - + 2: the S and M values for each intermediate result 3096res += ggml_type_size (GGML_TYPE_F32 )* (ne01_max * ne02 * ne03 * nwg * (ne20 + 2 )); 3097 } 3098 3099return res ; 3100} 3101 3102size_t ggml_metal_op_flash_attn_ext_extra_kv_f16 (const ggml_tensor * op ) { 3103assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 3104 3105// note: always reserve the temp buffer to avoid graph reallocations 3106//if (!ggml_metal_op_flash_attn_ext_use_kv_f16(op)) { 3107// return 0; 3108//} 3109 3110GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 3111 3112const size_t k_size = ggml_metal_op_flash_attn_ext_kv_f16_k_size (op ); 3113 3114// when V is a view of K, the dequantized V is a view of the dequantized K 3115const bool v_is_view_of_k = ggml_metal_op_flash_attn_ext_v_is_view_of_k (op ); 3116if (v_is_view_of_k ) { 3117return k_size ; 3118 } 3119 3120const size_t v_size = GGML_PAD (sizeof (ggml_fp16_t )* (size_t )ne20 * ne21 * ne22 * ne23 ,16 ); 3121 3122return k_size + v_size ; 3123} 3124 3125// size of the sparse index lists: one list of KV indices per mask row, 3126// padded with -1 up to a multiple of OP_FLASH_ATTN_EXT_VEC_NCPSG 3127size_t ggml_metal_op_flash_attn_ext_extra_idx (const ggml_tensor * op ) { 3128assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 3129 3130GGML_TENSOR_LOCALS (int32_t ,ne3 ,op -> src [3 ],ne ); 3131 3132const int n_kv_max = ggml_metal_op_flash_attn_ext_n_kv_max_sparse (op ); 3133 3134if (n_kv_max <=0 ) { 3135return 0 ; 3136 } 3137 3138const int n_kv_max_padded = GGML_PAD (n_kv_max ,OP_FLASH_ATTN_EXT_VEC_NCPSG ); 3139 3140return GGML_PAD (sizeof (int32_t )* (size_t )n_kv_max_padded * ne31 * ne32 * ne33 ,16 ); 3141} 3142 3143int ggml_metal_op_flash_attn_ext (ggml_metal_op_t ctx ,int idx ) { 3144ggml_tensor * op = ctx -> node (idx ); 3145 3146ggml_metal_library_t lib = ctx -> lib ; 3147ggml_metal_encoder_t enc = ctx -> enc ; 3148 3149const ggml_metal_device_props * props_dev = ggml_metal_device_get_props (ctx -> dev ); 3150 3151GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 3152GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 3153GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 3154GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 3155GGML_TENSOR_LOCALS (int32_t ,ne2 ,op -> src [2 ],ne ); 3156GGML_TENSOR_LOCALS (uint64_t ,nb2 ,op -> src [2 ],nb ); 3157GGML_TENSOR_LOCALS (int32_t ,ne3 ,op -> src [3 ],ne ); 3158GGML_TENSOR_LOCALS (uint64_t ,nb3 ,op -> src [3 ],nb ); 3159GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 3160GGML_TENSOR_LOCALS (int32_t ,nb ,op ,nb ); 3161 3162GGML_ASSERT (ne00 %4 == 0 ); 3163 3164GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 ); 3165GGML_ASSERT (op -> src [1 ]-> type == op -> src [2 ]-> type ); 3166 3167//GGML_ASSERT(ggml_are_same_shape (src1, src2)); 3168GGML_ASSERT (ne11 == ne21 ); 3169GGML_ASSERT (ne12 == ne22 ); 3170 3171GGML_ASSERT (!op -> src [3 ]|| op -> src [3 ]-> type == GGML_TYPE_F16 ); 3172GGML_ASSERT (!op -> src [3 ]|| op -> src [3 ]-> ne [1 ] >=op -> src [0 ]-> ne [1 ]&& 3173"the Flash-Attention Metal kernel requires the mask to be at least n_queries big" ); 3174 3175float scale ; 3176float max_bias ; 3177float logit_softcap ; 3178 3179memcpy (& scale , ((const int32_t * )op -> op_params )+ 0 ,sizeof (scale )); 3180memcpy (& max_bias , ((const int32_t * )op -> op_params )+ 1 ,sizeof (max_bias )); 3181memcpy (& logit_softcap , ((const int32_t * )op -> op_params )+ 2 ,sizeof (logit_softcap )); 3182 3183if (logit_softcap != 0.0f ) { 3184scale /=logit_softcap ; 3185 } 3186 3187const bool has_mask = op -> src [3 ]!= NULL ; 3188const bool has_sinks = op -> src [4 ]!= NULL ; 3189const bool has_bias = max_bias != 0.0f ; 3190const bool has_scap = logit_softcap != 0.0f ; 3191 3192const uint32_t n_head = op -> src [0 ]-> ne [2 ]; 3193const int32_t n_head_log2 = 1u << (uint32_t )floorf (log2f ((float )n_head )); 3194 3195const float m0 = powf (2.0f ,- (max_bias ) /n_head_log2 ); 3196const float m1 = powf (2.0f ,- (max_bias /2.0f ) /n_head_log2 ); 3197 3198GGML_ASSERT (ne01 < 65536 ); 3199 3200ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 3201ggml_metal_buffer_id bid_src1 = ggml_metal_get_buffer_id (op -> src [1 ]); 3202ggml_metal_buffer_id bid_src2 = ggml_metal_get_buffer_id (op -> src [2 ]); 3203ggml_metal_buffer_id bid_src3 = has_mask ?ggml_metal_get_buffer_id (op -> src [3 ]) :bid_src0 ; 3204ggml_metal_buffer_id bid_src4 = has_sinks ?ggml_metal_get_buffer_id (op -> src [4 ]) :bid_src0 ; 3205 3206ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 3207 3208ggml_metal_buffer_id bid_pad = bid_dst ; 3209bid_pad .offs += ggml_nbytes (op ); 3210 3211ggml_metal_buffer_id bid_blk = bid_pad ; 3212bid_blk .offs += ggml_metal_op_flash_attn_ext_extra_pad (op ); 3213 3214ggml_metal_buffer_id bid_tmp = bid_blk ; 3215bid_tmp .offs += ggml_metal_op_flash_attn_ext_extra_blk (op ); 3216 3217ggml_metal_buffer_id bid_kv_f16 = bid_tmp ; 3218bid_kv_f16 .offs += ggml_metal_op_flash_attn_ext_extra_tmp (op ); 3219 3220// sparse path: gather the finite mask entries into index lists and run the vec kernels over them 3221const int n_kv_max_sparse = ggml_metal_op_flash_attn_ext_n_kv_max_sparse (op ); 3222const bool use_sparse = n_kv_max_sparse > 0 ; 3223const int n_kv_max_padded = use_sparse ?GGML_PAD (n_kv_max_sparse ,OP_FLASH_ATTN_EXT_VEC_NCPSG ) :0 ; 3224 3225// the vec kernels dequantize the KV inline; no need for the F16 dequant pass in the sparse path 3226const bool use_kv_f16 = !use_sparse && ggml_metal_op_flash_attn_ext_use_kv_f16 (op ); 3227 3228ggml_metal_buffer_id bid_idx = bid_kv_f16 ; 3229bid_idx .offs += ggml_metal_op_flash_attn_ext_extra_kv_f16 (op ); 3230 3231ggml_metal_buffer_id bid_k = bid_src1 ; 3232ggml_metal_buffer_id bid_v = bid_src2 ; 3233 3234uint64_t nb10_attn = nb10 ; 3235uint64_t nb11_attn = nb11 ; 3236uint64_t nb12_attn = nb12 ; 3237uint64_t nb13_attn = nb13 ; 3238uint64_t nb20_attn = nb20 ; 3239uint64_t nb21_attn = nb21 ; 3240uint64_t nb22_attn = nb22 ; 3241uint64_t nb23_attn = nb23 ; 3242 3243if (use_kv_f16 ) { 3244assert (ggml_metal_op_flash_attn_ext_extra_kv_f16 (op )!= 0 ); 3245 3246const bool v_is_view_of_k = ggml_metal_op_flash_attn_ext_v_is_view_of_k (op ); 3247 3248const int64_t nblocks1_64 = (ne10 /ggml_blck_size (op -> src [1 ]-> type ))* (int64_t )ne11 * ne12 * ne13 ; 3249GGML_ASSERT (nblocks1_64 <=INT32_MAX ); 3250const int32_t nblocks1 = nblocks1_64 ; 3251 3252ggml_metal_buffer_id bid_v_f16 = bid_kv_f16 ; 3253bid_v_f16 .offs += ggml_metal_op_flash_attn_ext_kv_f16_k_size (op ); 3254 3255auto pipeline0 = ggml_metal_library_get_pipeline_flash_attn_ext_kv_f16 (lib ,op ); 3256const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline0 ),256 ); 3257 3258// K 3259ggml_metal_kargs_flash_attn_ext_kv_f16 args_k = { 3260/*.ne0 =*/ ne10 , 3261/*.ne1 =*/ ne11 , 3262/*.ne2 =*/ ne12 , 3263/*.ne3 =*/ ne13 , 3264/*.nb0 =*/ nb10 , 3265/*.nb1 =*/ nb11 , 3266/*.nb2 =*/ nb12 , 3267/*.nb3 =*/ nb13 , 3268/*.nblocks =*/ nblocks1 , 3269 }; 3270 3271ggml_metal_encoder_set_pipeline (enc ,pipeline0 ); 3272ggml_metal_encoder_set_bytes (enc ,& args_k ,sizeof (args_k ),0 ); 3273ggml_metal_encoder_set_buffer (enc ,bid_src1 ,1 ); 3274ggml_metal_encoder_set_buffer (enc ,bid_kv_f16 ,2 ); 3275 3276ggml_metal_encoder_dispatch_threadgroups (enc , (nblocks1 + nth - 1 )/nth ,1 ,1 ,nth ,1 ,1 ); 3277 3278// V (skip when V is a view of K: the dequantized V is a view of the dequantized K) 3279if (!v_is_view_of_k ) { 3280const int64_t nblocks2_64 = (ne20 /ggml_blck_size (op -> src [2 ]-> type ))* (int64_t )ne21 * ne22 * ne23 ; 3281GGML_ASSERT (nblocks2_64 <=INT32_MAX ); 3282const int32_t nblocks2 = nblocks2_64 ; 3283 3284ggml_metal_kargs_flash_attn_ext_kv_f16 args_v = { 3285/*.ne0 =*/ ne20 , 3286/*.ne1 =*/ ne21 , 3287/*.ne2 =*/ ne22 , 3288/*.ne3 =*/ ne23 , 3289/*.nb0 =*/ nb20 , 3290/*.nb1 =*/ nb21 , 3291/*.nb2 =*/ nb22 , 3292/*.nb3 =*/ nb23 , 3293/*.nblocks =*/ nblocks2 , 3294 }; 3295 3296ggml_metal_encoder_set_pipeline (enc ,pipeline0 ); 3297ggml_metal_encoder_set_bytes (enc ,& args_v ,sizeof (args_v ),0 ); 3298ggml_metal_encoder_set_buffer (enc ,bid_src2 ,1 ); 3299ggml_metal_encoder_set_buffer (enc ,bid_v_f16 ,2 ); 3300 3301ggml_metal_encoder_dispatch_threadgroups (enc , (nblocks2 + nth - 1 )/nth ,1 ,1 ,nth ,1 ,1 ); 3302 } 3303 3304// the pad and attention kernels read the dequantized KV 3305ggml_metal_op_concurrency_reset (ctx ); 3306 3307bid_k = bid_kv_f16 ; 3308bid_v = v_is_view_of_k ?bid_k :bid_v_f16 ; 3309 3310// contiguous F16 layout of the dequantized K 3311nb10_attn = sizeof (ggml_fp16_t ); 3312nb11_attn = nb10_attn * ne10 ; 3313nb12_attn = nb11_attn * ne11 ; 3314nb13_attn = nb12_attn * ne12 ; 3315 3316// if V is a view of K, the dequantized V is read from the dequantized K with K's strides 3317if (v_is_view_of_k ) { 3318nb20_attn = nb10_attn ; 3319nb21_attn = nb11_attn ; 3320nb22_attn = nb12_attn ; 3321nb23_attn = nb13_attn ; 3322 }else { 3323// contiguous F16 layout of the dequantized V 3324nb20_attn = sizeof (ggml_fp16_t ); 3325nb21_attn = nb20_attn * ne20 ; 3326nb22_attn = nb21_attn * ne21 ; 3327nb23_attn = nb22_attn * ne22 ; 3328 } 3329 } 3330 3331if (!use_sparse && !ggml_metal_op_flash_attn_ext_use_vec (op )) { 3332// half8x8 kernel 3333const int nqptg = OP_FLASH_ATTN_EXT_NQPSG ;// queries per threadgroup 3334const int ncpsg = OP_FLASH_ATTN_EXT_NCPSG ;// cache values per simdgroup 3335 3336GGML_ASSERT (nqptg <=32 ); 3337GGML_ASSERT (nqptg %8 == 0 ); 3338GGML_ASSERT (ncpsg %32 == 0 ); 3339 3340bool need_sync = false; 3341 3342const bool has_kvpad = ne11 %ncpsg != 0 ; 3343 3344if (has_kvpad ) { 3345assert (ggml_metal_op_flash_attn_ext_extra_pad (op )!= 0 ); 3346 3347ggml_metal_kargs_flash_attn_ext_pad args0 = { 3348/*.ne11 =*/ ne11 , 3349/*.ne_12_2 =*/ ne12 , 3350/*.ne_12_3 =*/ ne13 , 3351/*.nb11 =*/ nb11_attn , 3352/*.nb12 =*/ nb12_attn , 3353/*.nb13 =*/ nb13_attn , 3354/*.nb21 =*/ nb21_attn , 3355/*.nb22 =*/ nb22_attn , 3356/*.nb23 =*/ nb23_attn , 3357/*.ne31 =*/ ne31 , 3358/*.ne32 =*/ ne32 , 3359/*.ne33 =*/ ne33 , 3360/*.nb31 =*/ nb31 , 3361/*.nb32 =*/ nb32 , 3362/*.nb33 =*/ nb33 , 3363 }; 3364 3365auto pipeline0 = ggml_metal_library_get_pipeline_flash_attn_ext_pad (lib ,op ,has_mask ,ncpsg ); 3366 3367ggml_metal_encoder_set_pipeline (enc ,pipeline0 ); 3368ggml_metal_encoder_set_bytes (enc ,& args0 ,sizeof (args0 ),0 ); 3369ggml_metal_encoder_set_buffer (enc ,bid_k ,1 ); 3370ggml_metal_encoder_set_buffer (enc ,bid_v ,2 ); 3371ggml_metal_encoder_set_buffer (enc ,bid_src3 ,3 ); 3372ggml_metal_encoder_set_buffer (enc ,bid_pad ,4 ); 3373 3374assert (ne12 == ne22 ); 3375assert (ne13 == ne23 ); 3376 3377ggml_metal_encoder_dispatch_threadgroups (enc ,ncpsg , std::max (ne12 ,ne32 ), std::max (ne13 ,ne33 ),32 ,1 ,1 ); 3378 3379need_sync = true; 3380 } 3381 3382if (has_mask ) { 3383assert (ggml_metal_op_flash_attn_ext_extra_blk (op )!= 0 ); 3384 3385ggml_metal_kargs_flash_attn_ext_blk args0 = { 3386/*.ne01 =*/ ne01 , 3387/*.ne30 =*/ ne30 , 3388/*.ne31 =*/ ne31 , 3389/*.ne32 =*/ ne32 , 3390/*.ne33 =*/ ne33 , 3391/*.nb31 =*/ nb31 , 3392/*.nb32 =*/ nb32 , 3393/*.nb33 =*/ nb33 , 3394 }; 3395 3396auto pipeline0 = ggml_metal_library_get_pipeline_flash_attn_ext_blk (lib ,op ,nqptg ,ncpsg ); 3397 3398ggml_metal_encoder_set_pipeline (enc ,pipeline0 ); 3399ggml_metal_encoder_set_bytes (enc ,& args0 ,sizeof (args0 ),0 ); 3400ggml_metal_encoder_set_buffer (enc ,bid_src3 ,1 ); 3401ggml_metal_encoder_set_buffer (enc ,bid_blk ,2 ); 3402 3403const int32_t nblk1 = ((ne01 + nqptg - 1 )/nqptg ); 3404const int32_t nblk0 = ((ne30 + ncpsg - 1 )/ncpsg ); 3405 3406ggml_metal_encoder_dispatch_threadgroups (enc ,nblk0 ,nblk1 ,ne32 * ne33 ,32 ,1 ,1 ); 3407 3408need_sync = true; 3409 } 3410 3411if (need_sync ) { 3412ggml_metal_op_concurrency_reset (ctx ); 3413 } 3414 3415const int is_q = !use_kv_f16 && ggml_is_quantized (op -> src [1 ]-> type ) ?1 :0 ; 3416 3417// 2*(2*ncpsg) 3418// ncpsg soft_max values + ncpsg mask values 3419// 3420// 16*32*(nsg) 3421// the shared memory needed for the simdgroups to load the KV cache 3422// each thread loads (dequantizes) 16 head elements, there are 32 threads in th SG 3423// 3424#define FATTN_SMEM (nsg ) (GGML_PAD((nqptg*(ne00 + 2*GGML_PAD(ne20, 64) + 2*(2*ncpsg)) + is_q*(16*32*(nsg)))*(sizeof(float)/2), 16)) 3425 3426//int64_t nsgmax = 4; 3427// 3428//if (is_q) { 3429// nsgmax = 2; 3430// while (true) { 3431// const size_t smem = FATTN_SMEM(nsgmax); 3432// if (smem > props_dev->max_theadgroup_memory_size) { 3433// break; 3434// } 3435// nsgmax *= 2; 3436// } 3437// nsgmax /= 2; 3438//} 3439 3440// simdgroups per threadgroup (a.k.a. warps) 3441//nsg = ne01 <= nqptg ? MAX(4, MIN(nsgmax, MIN(ne11/ncpsg, (int64_t) pipeline.maxTotalThreadsPerThreadgroup/32))) : 4; 3442int32_t nsg = ne00 >=512 ?8 :4 ; 3443 3444const size_t smem = FATTN_SMEM (nsg ); 3445 3446const int32_t ns10 = nb11_attn /nb10_attn ; 3447const int32_t ns20 = nb21_attn /nb20_attn ; 3448 3449ggml_metal_kargs_flash_attn_ext args = { 3450/*.ne01 =*/ ne01 , 3451/*.ne02 =*/ ne02 , 3452/*.ne03 =*/ ne03 , 3453/*.nb01 =*/ nb01 , 3454/*.nb02 =*/ nb02 , 3455/*.nb03 =*/ nb03 , 3456/*.ne11 =*/ ne11 , 3457/*.ne_12_2 =*/ ne12 , 3458/*.ne_12_3 =*/ ne13 , 3459/*.ns10 =*/ ns10 , 3460/*.nb11 =*/ nb11_attn , 3461/*.nb12 =*/ nb12_attn , 3462/*.nb13 =*/ nb13_attn , 3463/*.ns20 =*/ ns20 , 3464/*.nb21 =*/ nb21_attn , 3465/*.nb22 =*/ nb22_attn , 3466/*.nb23 =*/ nb23_attn , 3467/*.ne31 =*/ ne31 , 3468/*.ne32 =*/ ne32 , 3469/*.ne33 =*/ ne33 , 3470/*.nb31 =*/ nb31 , 3471/*.nb32 =*/ nb32 , 3472/*.nb33 =*/ nb33 , 3473/*.ne1 =*/ ne1 , 3474/*.ne2 =*/ ne2 , 3475/*.ne3 =*/ ne3 , 3476/*.scale =*/ scale , 3477/*.max_bias =*/ max_bias , 3478/*.m0 =*/ m0 , 3479/*.m1 =*/ m1 , 3480/*.n_head_log2 =*/ n_head_log2 , 3481/*.logit_softcap =*/ logit_softcap , 3482 }; 3483 3484auto pipeline = ggml_metal_library_get_pipeline_flash_attn_ext (lib ,op ,has_mask ,has_sinks ,has_bias ,has_scap ,has_kvpad ,nsg ,use_kv_f16 ,ns10 ,ns20 ); 3485 3486ggml_metal_encoder_set_pipeline (enc ,pipeline ); 3487ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 3488ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 3489ggml_metal_encoder_set_buffer (enc ,bid_k ,2 ); 3490ggml_metal_encoder_set_buffer (enc ,bid_v ,3 ); 3491ggml_metal_encoder_set_buffer (enc ,bid_src3 ,4 ); 3492ggml_metal_encoder_set_buffer (enc ,bid_src4 ,5 ); 3493ggml_metal_encoder_set_buffer (enc ,bid_pad ,6 ); 3494ggml_metal_encoder_set_buffer (enc ,bid_blk ,7 ); 3495ggml_metal_encoder_set_buffer (enc ,bid_dst ,8 ); 3496 3497ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 3498 3499ggml_metal_encoder_dispatch_threadgroups (enc , (ne01 + nqptg - 1 )/nqptg ,ne02 ,ne03 ,32 ,nsg ,1 ); 3500#undef FATTN_SMEM 3501 }else { 3502// half4x4 kernel 3503// sparse: the index lists are per query row, so a threadgroup can share KV with Q == 1 only 3504auto cfg = use_sparse 3505 ? ggml_metal_tuning::fa_vec_baseline_cfg ((int )ne00 , (int )ne20 ) 3506 : ggml_metal_tuning::fa_vec_pick ( 3507props_dev -> device_id , 3508props_dev -> gpu_family , 3509 (int )op -> src [1 ]-> type , 3510 (int )ne00 , (int )ne20 ,// dk, dv (ne00 == dk for FA) 3511ne11 ,ne01 ); 3512 3513int nqptg = cfg .Q ;// queries per threadgroup 3514 3515const int ncpsg = OP_FLASH_ATTN_EXT_VEC_NCPSG ;// cache values per simdgroup !! sync with kernel template arguments !! 3516const int nhptg = 1 ;// heads per threadgroup 3517 3518GGML_ASSERT (nqptg <=32 ); 3519GGML_ASSERT (nqptg == 1 || nqptg == 2 || nqptg == 4 );// only instantiated Q values 3520GGML_ASSERT (ncpsg %32 == 0 ); 3521 3522bool need_sync = false; 3523 3524const bool has_kvpad = !use_sparse && ne11 %ncpsg != 0 ; 3525 3526if (use_sparse ) { 3527assert (ggml_metal_op_flash_attn_ext_extra_idx (op )!= 0 ); 3528 3529GGML_ASSERT (ne30 == ne11 ); 3530 3531ggml_metal_kargs_flash_attn_ext_vec_idx args0 = { 3532/*.ne30 =*/ ne30 , 3533/*.ne31 =*/ ne31 , 3534/*.ne32 =*/ ne32 , 3535/*.ne33 =*/ ne33 , 3536/*.nb31 =*/ nb31 , 3537/*.nb32 =*/ nb32 , 3538/*.nb33 =*/ nb33 , 3539/*.n_kv_max =*/ n_kv_max_sparse , 3540/*.n_kv_max_padded =*/ n_kv_max_padded , 3541 }; 3542 3543auto pipeline0 = ggml_metal_library_get_pipeline_flash_attn_ext_vec_idx (lib ,op ); 3544 3545ggml_metal_encoder_set_pipeline (enc ,pipeline0 ); 3546ggml_metal_encoder_set_bytes (enc ,& args0 ,sizeof (args0 ),0 ); 3547ggml_metal_encoder_set_buffer (enc ,bid_src3 ,1 ); 3548ggml_metal_encoder_set_buffer (enc ,bid_idx ,2 ); 3549 3550int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline0 ),256 ); 3551nth = std::max (32 , (nth /32 )* 32 ); 3552 3553ggml_metal_encoder_dispatch_threadgroups (enc ,ne31 ,ne32 ,ne33 ,nth ,1 ,1 ); 3554 3555need_sync = true; 3556 } 3557 3558if (has_kvpad ) { 3559assert (ggml_metal_op_flash_attn_ext_extra_pad (op )!= 0 ); 3560 3561ggml_metal_kargs_flash_attn_ext_pad args0 = { 3562/*.ne11 =*/ ne11 , 3563/*.ne_12_2 =*/ ne12 , 3564/*.ne_12_3 =*/ ne13 , 3565/*.nb11 =*/ nb11_attn , 3566/*.nb12 =*/ nb12_attn , 3567/*.nb13 =*/ nb13_attn , 3568/*.nb21 =*/ nb21_attn , 3569/*.nb22 =*/ nb22_attn , 3570/*.nb23 =*/ nb23_attn , 3571/*.ne31 =*/ ne31 , 3572/*.ne32 =*/ ne32 , 3573/*.ne33 =*/ ne33 , 3574/*.nb31 =*/ nb31 , 3575/*.nb32 =*/ nb32 , 3576/*.nb33 =*/ nb33 , 3577 }; 3578 3579auto pipeline0 = ggml_metal_library_get_pipeline_flash_attn_ext_pad (lib ,op ,has_mask ,ncpsg ); 3580 3581ggml_metal_encoder_set_pipeline (enc ,pipeline0 ); 3582ggml_metal_encoder_set_bytes (enc ,& args0 ,sizeof (args0 ),0 ); 3583ggml_metal_encoder_set_buffer (enc ,bid_k ,1 ); 3584ggml_metal_encoder_set_buffer (enc ,bid_v ,2 ); 3585ggml_metal_encoder_set_buffer (enc ,bid_src3 ,3 ); 3586ggml_metal_encoder_set_buffer (enc ,bid_pad ,4 ); 3587 3588assert (ne12 == ne22 ); 3589assert (ne13 == ne23 ); 3590 3591ggml_metal_encoder_dispatch_threadgroups (enc ,ncpsg , std::max (ne12 ,ne32 ), std::max (ne13 ,ne33 ),32 ,1 ,1 ); 3592 3593need_sync = true; 3594 } 3595 3596if (need_sync ) { 3597ggml_metal_op_concurrency_reset (ctx ); 3598 } 3599 3600// note: for simplicity assume the K is larger or equal than V 3601GGML_ASSERT (ne10 >=ne20 ); 3602 3603// ne00 + 2*ncpsg*(nsg) 3604// for each query, we load it as f16 in shared memory (ne00) 3605// and store the soft_max values and the mask 3606// 3607// ne20*(nsg) 3608// each simdgroup has a full f32 head vector in shared mem to accumulate results 3609// 3610#define FATTN_SMEM (nsg ) (GGML_PAD(((GGML_PAD(ne00, 128) + 4*ncpsg + 2*GGML_PAD(ne20, 128))*(nsg)*nqptg)*(sizeof(float)/2), 16)) 3611 3612int64_t nsg = 1 ; 3613 3614// workgroups 3615// each workgroup handles nsg*nkpsg cache values 3616int32_t nwg = 1 ; 3617if (use_sparse ) { 3618if (ne01 > 32 ) { 3619// large sparse batch 3620nwg = 1 ; 3621nsg = 1 ; 3622if (n_kv_max_padded == 640 ) { 3623nsg = 4 ;// 640 % (4*32) == 0 3624 }else { 3625while (2 * nwg * nsg * ncpsg < n_kv_max_padded && nsg < 4 ) { 3626nsg *=2 ; 3627 } 3628 } 3629 }else { 3630// small sparse batch 3631nwg = 32 ; 3632nsg = 1 ; 3633while (2 * nwg * nsg * ncpsg < n_kv_max_padded && nsg < 4 ) { 3634nsg *=2 ; 3635 } 3636 } 3637 }else { 3638nwg = 32 ; 3639nsg = 1 ; 3640while (2 * nwg * nsg * ncpsg < ne11 && nsg < 4 ) { 3641nsg *=2 ; 3642 } 3643 } 3644 3645// fall back to baseline (Q=1) if the tuned config exceeds threadgroup memory 3646if ((size_t )FATTN_SMEM (nsg )> props_dev -> max_theadgroup_memory_size ) { 3647cfg = ggml_metal_tuning::fa_vec_baseline_cfg ((int )ne00 , (int )ne20 ); 3648nqptg = cfg .Q ;// = 1 3649 } 3650 3651const int32_t ns10 = nb11_attn /nb10_attn ; 3652const int32_t ns20 = nb21_attn /nb20_attn ; 3653 3654ggml_metal_kargs_flash_attn_ext_vec args = { 3655/*.ne01 =*/ ne01 , 3656/*.ne02 =*/ ne02 , 3657/*.ne03 =*/ ne03 , 3658/*.nb01 =*/ nb01 , 3659/*.nb02 =*/ nb02 , 3660/*.nb03 =*/ nb03 , 3661/*.ne11 =*/ use_sparse ?n_kv_max_padded :ne11 , 3662/*.ne_12_2 =*/ ne12 , 3663/*.ne_12_3 =*/ ne13 , 3664/*.ns10 =*/ ns10 , 3665/*.nb11 =*/ nb11_attn , 3666/*.nb12 =*/ nb12_attn , 3667/*.nb13 =*/ nb13_attn , 3668/*.ns20 =*/ ns20 , 3669/*.nb21 =*/ nb21_attn , 3670/*.nb22 =*/ nb22_attn , 3671/*.nb23 =*/ nb23_attn , 3672/*.ne31 =*/ ne31 , 3673/*.ne32 =*/ ne32 , 3674/*.ne33 =*/ ne33 , 3675/*.nb31 =*/ nb31 , 3676/*.nb32 =*/ nb32 , 3677/*.nb33 =*/ nb33 , 3678/*.ne1 =*/ ne1 , 3679/*.ne2 =*/ ne2 , 3680/*.ne3 =*/ ne3 , 3681/*.scale =*/ scale , 3682/*.max_bias =*/ max_bias , 3683/*.m0 =*/ m0 , 3684/*.m1 =*/ m1 , 3685/*.n_head_log2 =*/ n_head_log2 , 3686/*.logit_softcap =*/ logit_softcap , 3687/*.n_kv_max_padded =*/ n_kv_max_padded , 3688 }; 3689 3690auto pipeline = ggml_metal_library_get_pipeline_flash_attn_ext_vec (lib ,op ,has_mask ,has_sinks ,has_bias ,has_scap ,has_kvpad ,use_sparse ,nqptg ,cfg .NE ,nsg ,nwg ,use_kv_f16 ,ns10 ,ns20 ); 3691 3692GGML_ASSERT (nsg * 32 <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 3693 3694ggml_metal_encoder_set_pipeline (enc ,pipeline ); 3695ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 3696ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 3697ggml_metal_encoder_set_buffer (enc ,bid_k ,2 ); 3698ggml_metal_encoder_set_buffer (enc ,bid_v ,3 ); 3699ggml_metal_encoder_set_buffer (enc ,bid_src3 ,4 ); 3700ggml_metal_encoder_set_buffer (enc ,bid_src4 ,5 ); 3701ggml_metal_encoder_set_buffer (enc ,use_sparse ?bid_idx :bid_src0 ,8 ); 3702 3703const size_t smem = FATTN_SMEM (nsg ); 3704 3705//printf("smem: %zu, max: %zu, nsg = %d, nsgmax = %d\n", smem, props_dev->max_theadgroup_memory_size, (int) nsg, (int) nsgmax); 3706GGML_ASSERT (smem <=props_dev -> max_theadgroup_memory_size ); 3707 3708if (nwg == 1 ) { 3709// using 1 workgroup -> write the result directly into dst 3710ggml_metal_encoder_set_buffer (enc ,bid_pad ,6 ); 3711ggml_metal_encoder_set_buffer (enc ,bid_dst ,7 ); 3712 3713ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 3714 3715ggml_metal_encoder_dispatch_threadgroups (enc , (ne01 + nqptg - 1 )/nqptg , (ne02 + nhptg - 1 )/nhptg ,ne03 * nwg ,32 ,nsg ,1 ); 3716 }else { 3717// sanity checks 3718assert (ggml_metal_op_flash_attn_ext_extra_tmp (op )!= 0 ); 3719 3720GGML_ASSERT (ne01 * ne02 * ne03 == ne1 * ne2 * ne3 ); 3721GGML_ASSERT ((uint64_t )ne1 * ne2 * ne3 <= (1u <<31 )); 3722 3723// write the results from each workgroup into a temp buffer 3724ggml_metal_encoder_set_buffer (enc ,bid_pad ,6 ); 3725ggml_metal_encoder_set_buffer (enc ,bid_tmp ,7 ); 3726 3727ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 3728ggml_metal_encoder_dispatch_threadgroups (enc , (ne01 + nqptg - 1 )/nqptg , (ne02 + nhptg - 1 )/nhptg ,ne03 * nwg ,32 ,nsg ,1 ); 3729 3730// sync the 2 kernels 3731ggml_metal_op_concurrency_reset (ctx ); 3732 3733// reduce the results from the workgroups 3734 { 3735const int32_t nrows = ne1 * ne2 * ne3 ; 3736 3737ggml_metal_kargs_flash_attn_ext_vec_reduce args0 = { 3738nrows , 3739 }; 3740 3741auto pipeline0 = ggml_metal_library_get_pipeline_flash_attn_ext_vec_reduce (lib ,op ,ne20 ,nwg ); 3742 3743ggml_metal_encoder_set_pipeline (enc ,pipeline0 ); 3744ggml_metal_encoder_set_bytes (enc ,& args0 ,sizeof (args0 ),0 ); 3745ggml_metal_encoder_set_buffer (enc ,bid_tmp ,1 ); 3746ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 3747 3748ggml_metal_encoder_dispatch_threadgroups (enc ,nrows ,1 ,1 ,32 * nwg ,1 ,1 ); 3749 } 3750 } 3751#undef FATTN_SMEM 3752 } 3753 3754return 1 ; 3755} 3756 3757int ggml_metal_op_bin (ggml_metal_op_t ctx ,int idx ) { 3758int n_fuse = 1 ; 3759const ggml_metal_fusion * fusion = nullptr ; 3760 3761if (ctx -> use_fusion ()) { 3762int n = 1 ; 3763fusion = ctx -> can_fuse (idx ,GGML_METAL_FUSION_FULL ,& n ); 3764n_fuse = n ; 3765 3766// snake activation autofuse: mul -> sin -> sqr -> mul -> add 3767if (fusion && fusion -> id == GGML_METAL_FUSION_SNAKE ) { 3768ctx -> count_fusions (fusion ); 3769return ggml_metal_op_snake_fused (ctx ,idx ); 3770 } 3771 } 3772 3773ggml_tensor * op = ctx -> node (idx ); 3774 3775ggml_metal_library_t lib = ctx -> lib ; 3776ggml_metal_encoder_t enc = ctx -> enc ; 3777 3778const bool use_fusion = ctx -> use_fusion (); 3779 3780const int debug_fusion = ggml_metal_fusion_info_debug (ctx -> finfo ); 3781 3782GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 3783GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 3784GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 3785GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 3786GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 3787GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 3788 3789GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 3790GGML_ASSERT (ggml_is_contiguous_rows (op -> src [1 ])); 3791 3792ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 3793ggml_metal_buffer_id bid_src1 = ggml_metal_get_buffer_id (op -> src [1 ]); 3794ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 3795 3796ggml_metal_kargs_bin args = { 3797/*.ne00 =*/ ne00 , 3798/*.ne01 =*/ ne01 , 3799/*.ne02 =*/ ne02 , 3800/*.ne03 =*/ ne03 , 3801/*.nb00 =*/ nb00 , 3802/*.nb01 =*/ nb01 , 3803/*.nb02 =*/ nb02 , 3804/*.nb03 =*/ nb03 , 3805/*.ne10 =*/ ne10 , 3806/*.ne11 =*/ ne11 , 3807/*.ne12 =*/ ne12 , 3808/*.ne13 =*/ ne13 , 3809/*.nb10 =*/ nb10 , 3810/*.nb11 =*/ nb11 , 3811/*.nb12 =*/ nb12 , 3812/*.nb13 =*/ nb13 , 3813/*.ne0 =*/ ne0 , 3814/*.ne1 =*/ ne1 , 3815/*.ne2 =*/ ne2 , 3816/*.ne3 =*/ ne3 , 3817/*.nb0 =*/ nb0 , 3818/*.nb1 =*/ nb1 , 3819/*.nb2 =*/ nb2 , 3820/*.nb3 =*/ nb3 , 3821/*.offs =*/ 0 , 3822/*.o1 =*/ {bid_src1 .offs }, 3823 }; 3824 3825// c[0] = add(a, b[0]) 3826// c[1] = add(c[0], b[1]) 3827// c[2] = add(c[1], b[2]) 3828// ... 3829if (use_fusion && fusion && fusion -> id == GGML_METAL_FUSION_ADD_CHAIN ) { 3830// the offsets of the fused addends are relative to the start of the src1 buffer 3831for (int i = 1 ;i < n_fuse ;i ++ ) { 3832args .o1 [i ]= ggml_metal_get_buffer_id (ctx -> node (idx + i )-> src [1 ]).offs ; 3833 } 3834 3835ctx -> count_fusions (fusion ); 3836 3837if (debug_fusion > 1 ) { 3838GGML_LOG_DEBUG ("%s: fuse: ADD x %d\n" ,__func__ ,n_fuse ); 3839 } 3840 } 3841 3842// the offsets of src1 and all fused buffers are relative to the start of the src1 buffer 3843bid_src1 .offs = 0 ; 3844 3845struct ggml_metal_pipeline_with_params pipeline ; 3846 3847pipeline = ggml_metal_library_get_pipeline_bin (lib ,op ,n_fuse ); 3848 3849if (n_fuse > 1 ) { 3850bid_dst = ggml_metal_get_buffer_id (ctx -> node (idx + n_fuse - 1 )); 3851 3852for (int i = 1 ;i < n_fuse ;++ i ) { 3853if (!ggml_metal_op_concurrency_check (ctx ,ctx -> node (idx + i ))) { 3854ggml_metal_op_concurrency_reset (ctx ); 3855 3856break ; 3857 } 3858 } 3859 } 3860 3861if (pipeline .c4 ) { 3862args .ne00 = ne00 /4 ; 3863args .ne10 = ne10 /4 ; 3864args .ne0 = ne0 /4 ; 3865 } 3866 3867ggml_metal_encoder_set_pipeline (enc ,pipeline ); 3868ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 3869ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 3870ggml_metal_encoder_set_buffer (enc ,bid_src1 ,2 ); 3871ggml_metal_encoder_set_buffer (enc ,bid_dst ,3 ); 3872 3873if (pipeline .cnt ) { 3874ggml_metal_encoder_dispatch_threadgroups (enc ,args .ne0 ,ggml_nrows (op ),1 ,1 ,1 ,1 ); 3875 }else { 3876const int nth_max = MIN (256 ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 3877 3878int nth = 1 ; 3879 3880while (2 * nth < args .ne0 && nth < nth_max ) { 3881nth *=2 ; 3882 } 3883 3884ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 3885 } 3886 3887return n_fuse ; 3888} 3889 3890int ggml_metal_op_silu_back (ggml_metal_op_t ctx ,int idx ) { 3891ggml_tensor * op = ctx -> node (idx ); 3892 3893ggml_metal_library_t lib = ctx -> lib ; 3894ggml_metal_encoder_t enc = ctx -> enc ; 3895 3896auto pipeline = ggml_metal_library_get_pipeline_silu_back (lib ,op ); 3897 3898const int64_t ne = ggml_nelements (op ); 3899 3900ggml_metal_kargs_silu_back args = { 3901/*.ne =*/ ne , 3902 }; 3903 3904int arg_idx {0 }; 3905 3906ggml_metal_encoder_set_pipeline (enc ,pipeline ); 3907ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),arg_idx ++ ); 3908ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),arg_idx ++ ); 3909ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),arg_idx ++ ); 3910ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),arg_idx ++ ); 3911 3912const int nth = std::min < int64_t > (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne ); 3913const int64_t n = (ne + nth - 1 ) /nth ; 3914 3915ggml_metal_encoder_dispatch_threadgroups (enc ,n ,1 ,1 ,nth ,1 ,1 ); 3916 3917return 1 ; 3918} 3919 3920int ggml_metal_op_l2_norm (ggml_metal_op_t ctx ,int idx ) { 3921ggml_tensor * op = ctx -> node (idx ); 3922 3923ggml_metal_library_t lib = ctx -> lib ; 3924ggml_metal_encoder_t enc = ctx -> enc ; 3925 3926GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 3927GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 3928GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 3929GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 3930 3931GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 3932 3933ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 3934ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 3935 3936float eps ; 3937memcpy (& eps ,op -> op_params ,sizeof (float )); 3938 3939ggml_metal_kargs_l2_norm args = { 3940/*.ne00 =*/ ne00 , 3941/*.ne01 =*/ ne01 , 3942/*.ne02 =*/ ne02 , 3943/*.ne03 =*/ ne03 , 3944/*.nb00 =*/ nb00 , 3945/*.nb01 =*/ nb01 , 3946/*.nb02 =*/ nb02 , 3947/*.nb03 =*/ nb03 , 3948/*.ne0 =*/ ne0 , 3949/*.ne1 =*/ ne1 , 3950/*.ne2 =*/ ne2 , 3951/*.ne3 =*/ ne3 , 3952/*.nb0 =*/ nb0 , 3953/*.nb1 =*/ nb1 , 3954/*.nb2 =*/ nb2 , 3955/*.nb3 =*/ nb3 , 3956/*.eps =*/ eps , 3957 }; 3958 3959auto pipeline = ggml_metal_library_get_pipeline_l2_norm (lib ,op ); 3960 3961if (pipeline .c4 ) { 3962args .ne00 = ne00 /4 ; 3963args .ne0 = ne0 /4 ; 3964 } 3965 3966int nth = 32 ;// SIMD width 3967 3968while (nth < ne00 && nth < ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 3969nth *=2 ; 3970 } 3971 3972nth = std::min (nth ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 3973 3974const size_t smem = pipeline .smem ; 3975 3976ggml_metal_encoder_set_pipeline (enc ,pipeline ); 3977ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 3978ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 3979ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 3980 3981ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 3982 3983ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 3984 3985return 1 ; 3986} 3987 3988int ggml_metal_op_group_norm (ggml_metal_op_t ctx ,int idx ) { 3989ggml_tensor * op = ctx -> node (idx ); 3990 3991ggml_metal_library_t lib = ctx -> lib ; 3992ggml_metal_encoder_t enc = ctx -> enc ; 3993 3994GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 3995GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 3996GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 3997GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 3998 3999const int32_t ngrp = ((const int32_t * )op -> op_params )[0 ]; 4000 4001float eps ; 4002memcpy (& eps ,op -> op_params + 1 ,sizeof (float )); 4003 4004ggml_metal_kargs_group_norm args = { 4005/*.ne00 =*/ ne00 , 4006/*.ne01 =*/ ne01 , 4007/*.ne02 =*/ ne02 , 4008/*.nb00 =*/ nb00 , 4009/*.nb01 =*/ nb01 , 4010/*.nb02 =*/ nb02 , 4011/*.ngrp =*/ ngrp , 4012/*.eps =*/ eps , 4013 }; 4014 4015auto pipeline = ggml_metal_library_get_pipeline_group_norm (lib ,op ); 4016 4017int nth = 32 ;// SIMD width 4018//while (nth < ne00/4 && nth < ggml_metal_pipeline_max_theads_per_threadgroup(pipeline)) { 4019// nth *= 2; 4020//} 4021 4022//nth = std::min(nth, ggml_metal_pipeline_max_theads_per_threadgroup(pipeline)); 4023//nth = std::min(nth, ne00/4); 4024 4025const size_t smem = pipeline .smem ; 4026 4027ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4028ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4029ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4030ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4031 4032ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 4033 4034ggml_metal_encoder_dispatch_threadgroups (enc ,ngrp ,1 ,1 ,nth ,1 ,1 ); 4035 4036return 1 ; 4037} 4038 4039int ggml_metal_op_norm (ggml_metal_op_t ctx ,int idx ) { 4040ggml_tensor * op = ctx -> node (idx ); 4041 4042ggml_metal_library_t lib = ctx -> lib ; 4043ggml_metal_encoder_t enc = ctx -> enc ; 4044 4045const bool use_fusion = ctx -> use_fusion (); 4046 4047const int debug_fusion = ggml_metal_fusion_info_debug (ctx -> finfo ); 4048 4049GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4050GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4051GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4052GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4053 4054float eps ; 4055memcpy (& eps ,op -> op_params ,sizeof (float )); 4056 4057ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 4058ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 4059 4060ggml_metal_kargs_norm args = { 4061/*.ne00 =*/ ne00 , 4062/*.ne00_t =*/ ne00 %4 == 0 ?ne00 /4 :ne00 , 4063/*.nb1 =*/ nb1 , 4064/*.nb2 =*/ nb2 , 4065/*.nb3 =*/ nb3 , 4066/*.eps =*/ eps , 4067/*.nef1 =*/ {ne01 }, 4068/*.nef2 =*/ {ne02 }, 4069/*.nef3 =*/ {ne03 }, 4070/*.nbf1 =*/ {nb01 }, 4071/*.nbf2 =*/ {nb02 }, 4072/*.nbf3 =*/ {nb03 }, 4073 }; 4074 4075int n_fuse = 1 ; 4076 4077ggml_metal_buffer_id bid_fuse [2 ]= {bid_src0 ,bid_src0 }; 4078 4079// d[0] = norm(a) 4080// d[1] = mul(d[0], b) 4081// d[2] = add(d[1], c) 4082if (use_fusion ) { 4083int n = 1 ; 4084const ggml_metal_fusion * fusion = ctx -> can_fuse (idx ,GGML_METAL_FUSION_FULL ,& n ); 4085 4086if (fusion && (fusion -> id == GGML_METAL_FUSION_NORM_MUL || fusion -> id == GGML_METAL_FUSION_NORM_MUL_ADD )) { 4087n_fuse = n ; 4088 4089ctx -> count_fusions (fusion ); 4090 4091for (int i = 1 ;i < n_fuse ;i ++ ) { 4092const ggml_tensor * fn = ctx -> node (idx + i ); 4093 4094bid_fuse [i - 1 ]= ggml_metal_get_buffer_id (fn -> src [1 ]); 4095 4096args .nef1 [i ]= fn -> src [1 ]-> ne [1 ]; 4097args .nef2 [i ]= fn -> src [1 ]-> ne [2 ]; 4098args .nef3 [i ]= fn -> src [1 ]-> ne [3 ]; 4099 4100args .nbf1 [i ]= fn -> src [1 ]-> nb [1 ]; 4101args .nbf2 [i ]= fn -> src [1 ]-> nb [2 ]; 4102args .nbf3 [i ]= fn -> src [1 ]-> nb [3 ]; 4103 } 4104 4105if (debug_fusion > 1 ) { 4106if (n_fuse == 2 ) { 4107GGML_LOG_DEBUG ("%s: fuse: %s + MUL\n" ,__func__ ,ggml_op_name (op -> op )); 4108 } 4109if (n_fuse == 3 ) { 4110GGML_LOG_DEBUG ("%s: fuse: %s + MUL + ADD\n" ,__func__ ,ggml_op_name (op -> op )); 4111 } 4112 } 4113 } 4114 } 4115 4116if (n_fuse > 1 ) { 4117bid_dst = ggml_metal_get_buffer_id (ctx -> node (idx + n_fuse - 1 )); 4118 4119for (int i = 1 ;i < n_fuse ;++ i ) { 4120if (!ggml_metal_op_concurrency_check (ctx ,ctx -> node (idx + i ))) { 4121ggml_metal_op_concurrency_reset (ctx ); 4122 4123break ; 4124 } 4125 } 4126 } 4127 4128auto pipeline = ggml_metal_library_get_pipeline_norm (lib ,op ,n_fuse ); 4129 4130int nth = 32 ;// SIMD width 4131 4132while (nth < args .ne00_t && nth < ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 4133nth *=2 ; 4134 } 4135 4136nth = std::min (nth ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 4137nth = std::min (nth , (args .ne00_t + 31 )/32 * 32 ); 4138 4139const size_t smem = pipeline .smem ; 4140 4141ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4142ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4143ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 4144ggml_metal_encoder_set_buffer (enc ,bid_fuse [0 ],2 ); 4145ggml_metal_encoder_set_buffer (enc ,bid_fuse [1 ],3 ); 4146ggml_metal_encoder_set_buffer (enc ,bid_dst ,4 ); 4147 4148ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 4149 4150ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 4151 4152return n_fuse ; 4153} 4154 4155int ggml_metal_op_rope (ggml_metal_op_t ctx ,int idx ) { 4156ggml_tensor * op = ctx -> node (idx ); 4157 4158ggml_metal_library_t lib = ctx -> lib ; 4159ggml_metal_encoder_t enc = ctx -> enc ; 4160 4161GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4162GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4163GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 4164GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 4165GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4166GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4167 4168// make sure we have one or more position id(ne10) per token(ne02) 4169GGML_ASSERT (ne10 %ne02 == 0 ); 4170GGML_ASSERT (ne10 >=ne02 ); 4171 4172const int nth = std::min (1024 ,ne00 ); 4173 4174const int n_past = ((const int32_t * )op -> op_params )[0 ]; 4175const int n_dims = ((const int32_t * )op -> op_params )[1 ]; 4176//const int mode = ((const int32_t *) op->op_params)[2]; 4177// skip 3, n_ctx, used in GLM RoPE, unimplemented in metal 4178const int n_ctx_orig = ((const int32_t * )op -> op_params )[4 ]; 4179 4180float freq_base ; 4181float freq_scale ; 4182float ext_factor ; 4183float attn_factor ; 4184float beta_fast ; 4185float beta_slow ; 4186 4187memcpy (& freq_base , (const int32_t * )op -> op_params + 5 ,sizeof (float )); 4188memcpy (& freq_scale , (const int32_t * )op -> op_params + 6 ,sizeof (float )); 4189memcpy (& ext_factor , (const int32_t * )op -> op_params + 7 ,sizeof (float )); 4190memcpy (& attn_factor , (const int32_t * )op -> op_params + 8 ,sizeof (float )); 4191memcpy (& beta_fast , (const int32_t * )op -> op_params + 9 ,sizeof (float )); 4192memcpy (& beta_slow , (const int32_t * )op -> op_params + 10 ,sizeof (float )); 4193 4194// mrope 4195const int sect_0 = ((const int32_t * )op -> op_params )[11 ]; 4196const int sect_1 = ((const int32_t * )op -> op_params )[12 ]; 4197const int sect_2 = ((const int32_t * )op -> op_params )[13 ]; 4198const int sect_3 = ((const int32_t * )op -> op_params )[14 ]; 4199 4200const int n_offs = ((const int32_t * )op -> op_params )[15 ]; 4201 4202// when dst aliases src0, the channels outside the rotated window already hold the correct data 4203const bool inplace = op -> data == op -> src [0 ]-> data ; 4204 4205ggml_metal_kargs_rope args = { 4206/*.ne00 =*/ ne00 , 4207/*.ne01 =*/ ne01 , 4208/*.ne02 =*/ ne02 , 4209/*.ne03 =*/ ne03 , 4210/*.nb00 =*/ nb00 , 4211/*.nb01 =*/ nb01 , 4212/*.nb02 =*/ nb02 , 4213/*.nb03 =*/ nb03 , 4214/*.ne0 =*/ ne0 , 4215/*.ne1 =*/ ne1 , 4216/*.ne2 =*/ ne2 , 4217/*.ne3 =*/ ne3 , 4218/*.nb0 =*/ nb0 , 4219/*.nb1 =*/ nb1 , 4220/*.nb2 =*/ nb2 , 4221/*.nb3 =*/ nb3 , 4222/*.n_past =*/ n_past , 4223/*.n_dims =*/ n_dims , 4224/*.n_offs =*/ n_offs , 4225/*.n_ctx_orig =*/ n_ctx_orig , 4226/*.freq_base =*/ freq_base , 4227/*.freq_scale =*/ freq_scale , 4228/*.ext_factor =*/ ext_factor , 4229/*.attn_factor =*/ attn_factor , 4230/*.beta_fast =*/ beta_fast , 4231/*.beta_slow =*/ beta_slow , 4232/* sect_0 =*/ sect_0 , 4233/* sect_1 =*/ sect_1 , 4234/* sect_2 =*/ sect_2 , 4235/* sect_3 =*/ sect_3 , 4236/* src2 =*/ op -> src [2 ]!= nullptr , 4237/* inplace =*/ inplace , 4238 }; 4239 4240auto pipeline = ggml_metal_library_get_pipeline_rope (lib ,op ); 4241 4242ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4243ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4244ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4245ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 4246if (op -> src [2 ]) { 4247ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),3 ); 4248 }else { 4249ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),3 ); 4250 } 4251ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),4 ); 4252 4253ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 4254 4255return 1 ; 4256} 4257 4258int ggml_metal_op_im2col (ggml_metal_op_t ctx ,int idx ) { 4259ggml_tensor * op = ctx -> node (idx ); 4260 4261ggml_metal_library_t lib = ctx -> lib ; 4262ggml_metal_encoder_t enc = ctx -> enc ; 4263 4264GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4265GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4266GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4267GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4268 4269const int32_t s0 = ((const int32_t * )(op -> op_params ))[0 ]; 4270const int32_t s1 = ((const int32_t * )(op -> op_params ))[1 ]; 4271const int32_t p0 = ((const int32_t * )(op -> op_params ))[2 ]; 4272const int32_t p1 = ((const int32_t * )(op -> op_params ))[3 ]; 4273const int32_t d0 = ((const int32_t * )(op -> op_params ))[4 ]; 4274const int32_t d1 = ((const int32_t * )(op -> op_params ))[5 ]; 4275 4276const bool is_2D = ((const int32_t * )(op -> op_params ))[6 ]== 1 ; 4277 4278const int32_t N = op -> src [1 ]-> ne [is_2D ?3 :2 ]; 4279const int32_t IC = op -> src [1 ]-> ne [is_2D ?2 :1 ]; 4280const int32_t IH = is_2D ?op -> src [1 ]-> ne [1 ] :1 ; 4281const int32_t IW = op -> src [1 ]-> ne [0 ]; 4282 4283const int32_t KH = is_2D ?op -> src [0 ]-> ne [1 ] :1 ; 4284const int32_t KW = op -> src [0 ]-> ne [0 ]; 4285 4286const int32_t OH = is_2D ?op -> ne [2 ] :1 ; 4287const int32_t OW = op -> ne [1 ]; 4288 4289const int32_t CHW = IC * KH * KW ; 4290 4291const uint64_t ofs0 = op -> src [1 ]-> nb [is_2D ?3 :2 ] /4 ; 4292const uint64_t ofs1 = op -> src [1 ]-> nb [is_2D ?2 :1 ] /4 ; 4293 4294ggml_metal_kargs_im2col args = { 4295/*.ofs0 =*/ ofs0 , 4296/*.ofs1 =*/ ofs1 , 4297/*.IW =*/ IW , 4298/*.IH =*/ IH , 4299/*.CHW =*/ CHW , 4300/*.s0 =*/ s0 , 4301/*.s1 =*/ s1 , 4302/*.p0 =*/ p0 , 4303/*.p1 =*/ p1 , 4304/*.d0 =*/ d0 , 4305/*.d1 =*/ d1 , 4306/*.N =*/ N , 4307/*.KH =*/ KH , 4308/*.KW =*/ KW , 4309/*.KHW =*/ KH * KW , 4310 }; 4311 4312auto pipeline = ggml_metal_library_get_pipeline_im2col (lib ,op ); 4313 4314if (KH * KW <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 4315const uint64_t ntptg0 = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )/(KH * KW ),N ); 4316 4317ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4318ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4319ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),1 ); 4320ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4321 4322ggml_metal_encoder_dispatch_threadgroups (enc ,IC ,OH ,OW ,ntptg0 ,KH ,KW ); 4323 }else { 4324const uint64_t n_threads = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),N ); 4325const int64_t quotient = N /n_threads + (N %n_threads > 0 ?1 :0 ); 4326 4327ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4328ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4329ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),1 ); 4330ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4331 4332ggml_metal_encoder_dispatch_threadgroups (enc ,quotient * CHW ,OH ,OW ,n_threads ,1 ,1 ); 4333 } 4334 4335return 1 ; 4336} 4337 4338int ggml_metal_op_conv_2d (ggml_metal_op_t ctx ,int idx ) { 4339ggml_tensor * op = ctx -> node (idx ); 4340 4341ggml_metal_library_t lib = ctx -> lib ; 4342ggml_metal_encoder_t enc = ctx -> enc ; 4343 4344GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4345GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4346GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 4347GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 4348GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4349GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4350 4351GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 4352GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 4353GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 4354GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_F32 ); 4355 4356const int32_t s0 = ((const int32_t * )op -> op_params )[0 ]; 4357const int32_t s1 = ((const int32_t * )op -> op_params )[1 ]; 4358const int32_t p0 = ((const int32_t * )op -> op_params )[2 ]; 4359const int32_t p1 = ((const int32_t * )op -> op_params )[3 ]; 4360const int32_t d0 = ((const int32_t * )op -> op_params )[4 ]; 4361const int32_t d1 = ((const int32_t * )op -> op_params )[5 ]; 4362 4363ggml_metal_kargs_conv_2d args = { 4364/*.nb00 =*/ nb00 , 4365/*.nb01 =*/ nb01 , 4366/*.nb02 =*/ nb02 , 4367/*.nb03 =*/ nb03 , 4368/*.nb10 =*/ nb10 , 4369/*.nb11 =*/ nb11 , 4370/*.nb12 =*/ nb12 , 4371/*.nb13 =*/ nb13 , 4372/*.nb0 =*/ nb0 , 4373/*.nb1 =*/ nb1 , 4374/*.nb2 =*/ nb2 , 4375/*.nb3 =*/ nb3 , 4376/*.IW =*/ ne10 , 4377/*.IH =*/ ne11 , 4378/*.KW =*/ ne00 , 4379/*.KH =*/ ne01 , 4380/*.IC =*/ ne02 , 4381/*.OC =*/ ne03 , 4382/*.OW =*/ ne0 , 4383/*.OH =*/ ne1 , 4384/*.N =*/ ne3 , 4385/*.s0 =*/ s0 , 4386/*.s1 =*/ s1 , 4387/*.p0 =*/ p0 , 4388/*.p1 =*/ p1 , 4389/*.d0 =*/ d0 , 4390/*.d1 =*/ d1 , 4391 }; 4392 4393auto pipeline = ggml_metal_library_get_pipeline_conv_2d (lib ,op ); 4394 4395int nth = ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ); 4396nth = std::min (nth ,256 ); 4397nth = std::max (nth ,1 ); 4398 4399const uint64_t n_out = ggml_nelements (op ); 4400 4401uint64_t tg = (n_out + nth - 1 )/nth ; 4402tg = std::max < uint64_t > (tg ,1 ); 4403tg = std::min < uint64_t > (tg , (uint64_t ) std::numeric_limits < int > ::max ()); 4404 4405ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4406ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4407ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4408ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 4409ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 4410 4411ggml_metal_encoder_dispatch_threadgroups (enc ,tg ,1 ,1 ,nth ,1 ,1 ); 4412 4413return 1 ; 4414} 4415 4416int ggml_metal_op_conv_2d_dw (ggml_metal_op_t ctx ,int idx ) { 4417ggml_tensor * op = ctx -> node (idx ); 4418 4419ggml_metal_library_t lib = ctx -> lib ; 4420ggml_metal_encoder_t enc = ctx -> enc ; 4421 4422GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4423GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4424GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 4425GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 4426GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4427GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4428 4429GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 4430GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 4431GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_F32 ); 4432 4433const int32_t s0 = ((const int32_t * )op -> op_params )[0 ]; 4434const int32_t s1 = ((const int32_t * )op -> op_params )[1 ]; 4435const int32_t p0 = ((const int32_t * )op -> op_params )[2 ]; 4436const int32_t p1 = ((const int32_t * )op -> op_params )[3 ]; 4437const int32_t d0 = ((const int32_t * )op -> op_params )[4 ]; 4438const int32_t d1 = ((const int32_t * )op -> op_params )[5 ]; 4439 4440ggml_metal_kargs_conv_2d_dw args = { 4441/*.nb00 =*/ nb00 , 4442/*.nb01 =*/ nb01 , 4443/*.nb02 =*/ nb03 , 4444/*.nb10 =*/ nb10 , 4445/*.nb11 =*/ nb11 , 4446/*.nb12 =*/ nb12 , 4447/*.nb13 =*/ nb13 , 4448/*.nb0 =*/ nb0 , 4449/*.nb1 =*/ nb1 , 4450/*.nb2 =*/ nb2 , 4451/*.nb3 =*/ nb3 , 4452/*.IW =*/ ne10 , 4453/*.IH =*/ ne11 , 4454/*.KW =*/ ne00 , 4455/*.KH =*/ ne01 , 4456/*.C =*/ ne12 , 4457/*.OW =*/ ne0 , 4458/*.OH =*/ ne1 , 4459/*.N =*/ ne13 , 4460/*.s0 =*/ s0 , 4461/*.s1 =*/ s1 , 4462/*.p0 =*/ p0 , 4463/*.p1 =*/ p1 , 4464/*.d0 =*/ d0 , 4465/*.d1 =*/ d1 , 4466 }; 4467 4468const bool use_tiled = (nb12 < nb10 ); 4469 4470auto pipeline = ggml_metal_library_get_pipeline_conv_2d_dw (lib ,op ,use_tiled ); 4471 4472int nth = ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ); 4473nth = std::min (nth ,256 ); 4474nth = std::max (nth ,1 ); 4475 4476const int32_t OW = ne0 ; 4477const int32_t OH = ne1 ; 4478const int32_t C = ne12 ; 4479const int32_t N = ne13 ; 4480 4481const int tg_x = use_tiled ? (C + nth - 1 ) /nth : (OW + nth - 1 ) /nth ; 4482const int tg_y = OH ; 4483const int tg_z = use_tiled ?OW * N :C * N ; 4484 4485ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4486ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4487ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4488ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 4489ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 4490 4491ggml_metal_encoder_dispatch_threadgroups (enc ,tg_x ,tg_y ,tg_z ,nth ,1 ,1 ); 4492 4493return 1 ; 4494} 4495 4496int ggml_metal_op_conv_3d (ggml_metal_op_t ctx ,int idx ) { 4497ggml_tensor * op = ctx -> node (idx ); 4498 4499ggml_metal_library_t lib = ctx -> lib ; 4500ggml_metal_encoder_t enc = ctx -> enc ; 4501 4502// 1. Extract standard dimensions and byte strides 4503GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4504GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 4505GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4506 4507// 2. Extract hyperparams from op_params 4508const int32_t s0 = ((const int32_t * )(op -> op_params ))[0 ]; 4509const int32_t s1 = ((const int32_t * )(op -> op_params ))[1 ]; 4510const int32_t s2 = ((const int32_t * )(op -> op_params ))[2 ]; 4511const int32_t p0 = ((const int32_t * )(op -> op_params ))[3 ]; 4512const int32_t p1 = ((const int32_t * )(op -> op_params ))[4 ]; 4513const int32_t p2 = ((const int32_t * )(op -> op_params ))[5 ]; 4514const int32_t d0 = ((const int32_t * )(op -> op_params ))[6 ]; 4515const int32_t d1 = ((const int32_t * )(op -> op_params ))[7 ]; 4516const int32_t d2 = ((const int32_t * )(op -> op_params ))[8 ]; 4517const int32_t IC = ((const int32_t * )(op -> op_params ))[9 ]; 4518const int32_t N = ((const int32_t * )(op -> op_params ))[10 ]; 4519const int32_t OC = ((const int32_t * )(op -> op_params ))[11 ]; 4520 4521// 3. Build the parameter struct using the macro-generated variables 4522ggml_metal_kargs_conv_3d args = { 4523/*.IW =*/ (int32_t )op -> src [1 ]-> ne [0 ], 4524/*.IH =*/ (int32_t )op -> src [1 ]-> ne [1 ], 4525/*.ID =*/ (int32_t )op -> src [1 ]-> ne [2 ], 4526/*.OW =*/ (int32_t )op -> ne [0 ], 4527/*.OH =*/ (int32_t )op -> ne [1 ], 4528/*.OD =*/ (int32_t )op -> ne [2 ], 4529/*.KW =*/ (int32_t )op -> src [0 ]-> ne [0 ], 4530/*.KH =*/ (int32_t )op -> src [0 ]-> ne [1 ], 4531/*.KD =*/ (int32_t )op -> src [0 ]-> ne [2 ], 4532s0 ,s1 ,s2 , 4533p0 ,p1 ,p2 , 4534d0 ,d1 ,d2 , 4535IC ,N ,OC , 4536nb00 ,nb01 ,nb02 ,nb03 ,// Weight strides 4537nb10 ,nb11 ,nb12 ,nb13 ,// Input strides 4538nb0 ,nb1 ,nb2 ,nb3 // Output strides 4539 }; 4540 4541// 4. Fetch the JIT pipeline 4542auto pipeline = ggml_metal_library_get_pipeline_conv_3d (lib ,op ); 4543 4544// 5. Grid mapping 4545int nth0 = 32 ;// Standard SIMD width for Apple Silicon 4546int nth1 = 1 ; 4547int nth2 = 1 ; 4548 4549int64_t spatial_volume = args .OW * args .OH * args .OD ; 4550 4551int ntg0 = (spatial_volume + nth0 - 1 ) /nth0 ; 4552int ntg1 = args .OC ; 4553int ntg2 = args .N ; 4554 4555// 6. Bind and Dispatch via the ggml C wrapper 4556ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4557ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4558ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4559ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 4560ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 4561 4562ggml_metal_encoder_dispatch_threadgroups (enc ,ntg0 ,ntg1 ,ntg2 ,nth0 ,nth1 ,nth2 ); 4563 4564return 1 ; 4565} 4566 4567int ggml_metal_op_conv_transpose_1d (ggml_metal_op_t ctx ,int idx ) { 4568ggml_tensor * op = ctx -> node (idx ); 4569 4570ggml_metal_library_t lib = ctx -> lib ; 4571ggml_metal_encoder_t enc = ctx -> enc ; 4572 4573GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4574GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4575GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 4576GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 4577GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4578GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4579 4580const int32_t s0 = ((const int32_t * )(op -> op_params ))[0 ]; 4581 4582const int32_t IC = op -> src [1 ]-> ne [1 ]; 4583const int32_t IL = op -> src [1 ]-> ne [0 ]; 4584 4585const int32_t K = op -> src [0 ]-> ne [0 ]; 4586 4587const int32_t OL = op -> ne [0 ]; 4588const int32_t OC = op -> ne [1 ]; 4589 4590ggml_metal_kargs_conv_transpose_1d args = { 4591/*.IC =*/ IC , 4592/*.IL =*/ IL , 4593/*.K =*/ K , 4594/*.s0 =*/ s0 , 4595/*.nb0 =*/ nb0 , 4596/*.nb1 =*/ nb1 , 4597 }; 4598 4599auto pipeline = ggml_metal_library_get_pipeline_conv_transpose_1d (lib ,op ); 4600 4601ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4602ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4603ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4604ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 4605ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 4606 4607ggml_metal_encoder_dispatch_threadgroups (enc ,OL ,OC ,1 ,1 ,1 ,1 ); 4608 4609return 1 ; 4610} 4611 4612int ggml_metal_op_col2im_1d (ggml_metal_op_t ctx ,int idx ) { 4613ggml_tensor * op = ctx -> node (idx ); 4614 4615ggml_metal_library_t lib = ctx -> lib ; 4616ggml_metal_encoder_t enc = ctx -> enc ; 4617 4618const int32_t s0 = ((const int32_t * )(op -> op_params ))[0 ]; 4619const int32_t OC = ((const int32_t * )(op -> op_params ))[1 ]; 4620const int32_t p0 = ((const int32_t * )(op -> op_params ))[2 ]; 4621 4622const int32_t K_OC = (int32_t )op -> src [0 ]-> ne [0 ]; 4623const int32_t T_in = (int32_t )op -> src [0 ]-> ne [1 ]; 4624const int32_t K = K_OC /OC ; 4625const int32_t T_out = (int32_t )op -> ne [0 ]; 4626 4627ggml_metal_kargs_col2im_1d args = { 4628/*.T_in =*/ T_in , 4629/*.T_out =*/ T_out , 4630/*.OC =*/ OC , 4631/*.K =*/ K , 4632/*.K_OC =*/ K_OC , 4633/*.s0 =*/ s0 , 4634/*.p0 =*/ p0 , 4635 }; 4636 4637auto pipeline = ggml_metal_library_get_pipeline_col2im_1d (lib ,op ); 4638 4639const int total = T_out * OC ; 4640const int nth = 256 ; 4641const int ntg = (total + nth - 1 ) /nth ; 4642 4643ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4644ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4645ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4646ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4647 4648ggml_metal_encoder_dispatch_threadgroups (enc ,ntg ,1 ,1 ,nth ,1 ,1 ); 4649 4650return 1 ; 4651} 4652 4653// Dispatch the fused snake kernel from the matched mul -> sin -> sqr -> mul -> add chain. 4654// idx points at the leading mul. The caller has validated the chain. 4655int ggml_metal_op_snake_fused (ggml_metal_op_t ctx ,int idx ) { 4656ggml_metal_library_t lib = ctx -> lib ; 4657ggml_metal_encoder_t enc = ctx -> enc ; 4658 4659const ggml_tensor * mul0 = ctx -> node (idx + 0 ); 4660const ggml_tensor * sqr = ctx -> node (idx + 2 ); 4661const ggml_tensor * mul1 = ctx -> node (idx + 3 ); 4662ggml_tensor * add = ctx -> node (idx + 4 ); 4663 4664const ggml_tensor * x = ggml_are_same_shape (mul0 ,mul0 -> src [0 ]) ?mul0 -> src [0 ] :mul0 -> src [1 ]; 4665const ggml_tensor * a = (x == mul0 -> src [0 ]) ?mul0 -> src [1 ] :mul0 -> src [0 ]; 4666const ggml_tensor * inv_b = (mul1 -> src [0 ]== sqr ) ?mul1 -> src [1 ] :mul1 -> src [0 ]; 4667 4668const int T = (int )x -> ne [0 ]; 4669const int C = (int )x -> ne [1 ]; 4670const int total = T * C ; 4671 4672// the encode loop pre-checked the leading mul only, check the rest of the chain 4673for (int i = 1 ;i < 5 ;++ i ) { 4674if (!ggml_metal_op_concurrency_check (ctx ,ctx -> node (idx + i ))) { 4675ggml_metal_op_concurrency_reset (ctx ); 4676 4677break ; 4678 } 4679 } 4680 4681auto pipeline = ggml_metal_library_get_pipeline_snake (lib ,x -> type ); 4682 4683ggml_metal_kargs_snake args = { 4684/*.T =*/ T , 4685/*.C =*/ C , 4686 }; 4687 4688ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4689ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4690ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (x ),1 ); 4691ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (a ),2 ); 4692ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (inv_b ),3 ); 4693ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (add ),4 ); 4694 4695const int nth = 256 ; 4696const int ntg = (total + nth - 1 ) /nth ; 4697ggml_metal_encoder_dispatch_threadgroups (enc ,ntg ,1 ,1 ,nth ,1 ,1 ); 4698 4699return 5 ; 4700} 4701 4702int ggml_metal_op_conv_transpose_2d (ggml_metal_op_t ctx ,int idx ) { 4703ggml_tensor * op = ctx -> node (idx ); 4704 4705ggml_metal_library_t lib = ctx -> lib ; 4706ggml_metal_encoder_t enc = ctx -> enc ; 4707 4708GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4709GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4710GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 4711GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 4712GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4713GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4714 4715const int32_t s0 = ((const int32_t * )(op -> op_params ))[0 ]; 4716 4717const int32_t IC = op -> src [1 ]-> ne [2 ]; 4718const int32_t IH = op -> src [1 ]-> ne [1 ]; 4719const int32_t IW = op -> src [1 ]-> ne [0 ]; 4720 4721const int32_t KH = op -> src [0 ]-> ne [1 ]; 4722const int32_t KW = op -> src [0 ]-> ne [0 ]; 4723 4724const int32_t OW = op -> ne [0 ]; 4725const int32_t OH = op -> ne [1 ]; 4726const int32_t OC = op -> ne [2 ]; 4727const int32_t N = op -> src [1 ]-> ne [3 ]; 4728 4729ggml_metal_kargs_conv_transpose_2d args = { 4730/*.IC =*/ IC , 4731/*.IH =*/ IH , 4732/*.IW =*/ IW , 4733/*.KH =*/ KH , 4734/*.KW =*/ KW , 4735/*.OC =*/ OC , 4736/*.s0 =*/ s0 , 4737/*.nb0 =*/ nb0 , 4738/*.nb1 =*/ nb1 , 4739/*.nb2 =*/ nb2 , 4740/*.nb3 =*/ nb3 , 4741 }; 4742 4743auto pipeline = ggml_metal_library_get_pipeline_conv_transpose_2d (lib ,op ); 4744 4745ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4746ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4747ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4748ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 4749ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 4750 4751// Metal requires buffer size to be multiple of 16 bytes 4752const size_t smem = GGML_PAD (KW * KH * sizeof (float ),16 ); 4753ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 4754 4755ggml_metal_encoder_dispatch_threadgroups (enc ,OW ,OH ,OC * N ,KW ,KH ,1 ); 4756 4757return 1 ; 4758} 4759 4760int ggml_metal_op_upscale (ggml_metal_op_t ctx ,int idx ) { 4761ggml_tensor * op = ctx -> node (idx ); 4762 4763ggml_metal_library_t lib = ctx -> lib ; 4764ggml_metal_encoder_t enc = ctx -> enc ; 4765 4766GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4767GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4768GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4769GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4770 4771float sf0 = (float )ne0 /op -> src [0 ]-> ne [0 ]; 4772float sf1 = (float )ne1 /op -> src [0 ]-> ne [1 ]; 4773float sf2 = (float )ne2 /op -> src [0 ]-> ne [2 ]; 4774float sf3 = (float )ne3 /op -> src [0 ]-> ne [3 ]; 4775 4776const int32_t mode_flags = ggml_get_op_params_i32 (op ,0 ); 4777 4778float poffs = 0.5f ; 4779 4780if (mode_flags & GGML_SCALE_FLAG_ALIGN_CORNERS ) { 4781poffs = 0.0f ; 4782sf0 = ne0 > 1 && ne00 > 1 ? (float )(ne0 - 1 ) / (ne00 - 1 ) :sf0 ; 4783sf1 = ne1 > 1 && ne01 > 1 ? (float )(ne1 - 1 ) / (ne01 - 1 ) :sf1 ; 4784 } 4785 4786ggml_metal_kargs_upscale args = { 4787/*.ne00 =*/ ne00 , 4788/*.ne01 =*/ ne01 , 4789/*.ne02 =*/ ne02 , 4790/*.ne03 =*/ ne03 , 4791/*.nb00 =*/ nb00 , 4792/*.nb01 =*/ nb01 , 4793/*.nb02 =*/ nb02 , 4794/*.nb03 =*/ nb03 , 4795/*.ne0 =*/ ne0 , 4796/*.ne1 =*/ ne1 , 4797/*.ne2 =*/ ne2 , 4798/*.ne3 =*/ ne3 , 4799/*.nb0 =*/ nb0 , 4800/*.nb1 =*/ nb1 , 4801/*.nb2 =*/ nb2 , 4802/*.nb3 =*/ nb3 , 4803/*.sf0 =*/ sf0 , 4804/*.sf1 =*/ sf1 , 4805/*.sf2 =*/ sf2 , 4806/*.sf3 =*/ sf3 , 4807/*.poffs =*/ poffs , 4808 }; 4809 4810auto pipeline = ggml_metal_library_get_pipeline_upscale (lib ,op ); 4811 4812const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne0 ); 4813 4814ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4815ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4816ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4817ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4818 4819ggml_metal_encoder_dispatch_threadgroups (enc ,ne1 ,ne2 ,ne3 ,nth ,1 ,1 ); 4820 4821return 1 ; 4822} 4823 4824int ggml_metal_op_roll (ggml_metal_op_t ctx ,int idx ) { 4825ggml_tensor * op = ctx -> node (idx ); 4826 4827ggml_metal_library_t lib = ctx -> lib ; 4828ggml_metal_encoder_t enc = ctx -> enc ; 4829 4830GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4831GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4832GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4833GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4834 4835const int32_t s0 = ggml_get_op_params_i32 (op ,0 ); 4836const int32_t s1 = ggml_get_op_params_i32 (op ,1 ); 4837const int32_t s2 = ggml_get_op_params_i32 (op ,2 ); 4838const int32_t s3 = ggml_get_op_params_i32 (op ,3 ); 4839 4840ggml_metal_kargs_roll args = { 4841/*.ne00 =*/ ne00 , 4842/*.ne01 =*/ ne01 , 4843/*.ne02 =*/ ne02 , 4844/*.ne03 =*/ ne03 , 4845/*.nb00 =*/ nb00 , 4846/*.nb01 =*/ nb01 , 4847/*.nb02 =*/ nb02 , 4848/*.nb03 =*/ nb03 , 4849/*.ne0 =*/ ne0 , 4850/*.ne1 =*/ ne1 , 4851/*.ne2 =*/ ne2 , 4852/*.ne3 =*/ ne3 , 4853/*.nb0 =*/ nb0 , 4854/*.nb1 =*/ nb1 , 4855/*.nb2 =*/ nb2 , 4856/*.nb3 =*/ nb3 , 4857/*.s0 =*/ s0 , 4858/*.s1 =*/ s1 , 4859/*.s2 =*/ s2 , 4860/*.s3 =*/ s3 4861 }; 4862 4863auto pipeline = ggml_metal_library_get_pipeline_roll (lib ,op ); 4864 4865const int nth = std::min (1024 ,ne0 ); 4866 4867ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4868ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4869ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4870ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4871 4872ggml_metal_encoder_dispatch_threadgroups (enc ,ne1 ,ne2 ,ne3 ,nth ,1 ,1 ); 4873 4874return 1 ; 4875} 4876 4877int ggml_metal_op_pad (ggml_metal_op_t ctx ,int idx ) { 4878ggml_tensor * op = ctx -> node (idx ); 4879 4880ggml_metal_library_t lib = ctx -> lib ; 4881ggml_metal_encoder_t enc = ctx -> enc ; 4882 4883GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4884GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4885GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4886GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4887 4888ggml_metal_kargs_pad args = { 4889/*.ne00 =*/ ne00 , 4890/*.ne01 =*/ ne01 , 4891/*.ne02 =*/ ne02 , 4892/*.ne03 =*/ ne03 , 4893/*.nb00 =*/ nb00 , 4894/*.nb01 =*/ nb01 , 4895/*.nb02 =*/ nb02 , 4896/*.nb03 =*/ nb03 , 4897/*.ne0 =*/ ne0 , 4898/*.ne1 =*/ ne1 , 4899/*.ne2 =*/ ne2 , 4900/*.ne3 =*/ ne3 , 4901/*.nb0 =*/ nb0 , 4902/*.nb1 =*/ nb1 , 4903/*.nb2 =*/ nb2 , 4904/*.nb3 =*/ nb3 4905 }; 4906 4907auto pipeline = ggml_metal_library_get_pipeline_pad (lib ,op ); 4908 4909if (pipeline .c4 ) { 4910args .ne00 = ne00 /4 ; 4911args .ne0 = ne0 /4 ; 4912 } 4913 4914const int nth_max = MIN (64 ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 4915const int nth = MIN (args .ne0 ,nth_max ); 4916const int nk0 = (args .ne0 + 1024 - 1 )/1024 ;// note: 1024 is hardcoded in the kernel! 4917 4918ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4919ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4920ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4921ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4922 4923ggml_metal_encoder_dispatch_threadgroups (enc ,nk0 * ne1 ,ne2 ,ne3 ,nth ,1 ,1 ); 4924 4925return 1 ; 4926} 4927 4928int ggml_metal_op_pad_reflect_1d (ggml_metal_op_t ctx ,int idx ) { 4929ggml_tensor * op = ctx -> node (idx ); 4930 4931ggml_metal_library_t lib = ctx -> lib ; 4932ggml_metal_encoder_t enc = ctx -> enc ; 4933 4934GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 4935GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 4936GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4937GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4938 4939ggml_metal_kargs_pad_reflect_1d args = { 4940/*.ne00 =*/ ne00 , 4941/*.ne01 =*/ ne01 , 4942/*.ne02 =*/ ne02 , 4943/*.ne03 =*/ ne03 , 4944/*.nb00 =*/ nb00 , 4945/*.nb01 =*/ nb01 , 4946/*.nb02 =*/ nb02 , 4947/*.nb03 =*/ nb03 , 4948/*.ne0 =*/ ne0 , 4949/*.ne1 =*/ ne1 , 4950/*.ne2 =*/ ne2 , 4951/*.ne3 =*/ ne3 , 4952/*.nb0 =*/ nb0 , 4953/*.nb1 =*/ nb1 , 4954/*.nb2 =*/ nb2 , 4955/*.nb3 =*/ nb3 , 4956/*.p0 =*/ ((const int32_t * )(op -> op_params ))[0 ], 4957/*.p1 =*/ ((const int32_t * )(op -> op_params ))[1 ] 4958 }; 4959 4960auto pipeline = ggml_metal_library_get_pipeline_pad_reflect_1d (lib ,op ); 4961 4962const int nth = std::min (1024 ,ne0 ); 4963 4964ggml_metal_encoder_set_pipeline (enc ,pipeline ); 4965ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 4966ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 4967ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 4968 4969ggml_metal_encoder_dispatch_threadgroups (enc ,ne1 ,ne2 ,ne3 ,nth ,1 ,1 ); 4970 4971return 1 ; 4972} 4973 4974int ggml_metal_op_arange (ggml_metal_op_t ctx ,int idx ) { 4975ggml_tensor * op = ctx -> node (idx ); 4976 4977ggml_metal_library_t lib = ctx -> lib ; 4978ggml_metal_encoder_t enc = ctx -> enc ; 4979 4980GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 4981GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 4982 4983float start ; 4984float step ; 4985 4986memcpy (& start , ((const int32_t * )op -> op_params )+ 0 ,sizeof (float )); 4987memcpy (& step , ((const int32_t * )op -> op_params )+ 2 ,sizeof (float )); 4988 4989ggml_metal_kargs_arange args = { 4990/*.ne0 =*/ ne0 , 4991/*.start =*/ start , 4992/*.step =*/ step 4993 }; 4994 4995const int nth = std::min (1024 ,ne0 ); 4996 4997auto pipeline = ggml_metal_library_get_pipeline_arange (lib ,op ); 4998 4999ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5000ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5001ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),1 ); 5002 5003ggml_metal_encoder_dispatch_threadgroups (enc ,1 ,1 ,1 ,nth ,1 ,1 ); 5004 5005return 1 ; 5006} 5007 5008int ggml_metal_op_timestep_embedding (ggml_metal_op_t ctx ,int idx ) { 5009ggml_tensor * op = ctx -> node (idx ); 5010 5011ggml_metal_library_t lib = ctx -> lib ; 5012ggml_metal_encoder_t enc = ctx -> enc ; 5013 5014GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5015GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5016GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 5017GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 5018 5019const int dim = op -> op_params [0 ]; 5020const int max_period = op -> op_params [1 ]; 5021 5022ggml_metal_kargs_timestep_embedding args = { 5023/*.nb1 =*/ nb1 , 5024/*.dim =*/ dim , 5025/*.max_period =*/ max_period , 5026 }; 5027 5028auto pipeline = ggml_metal_library_get_pipeline_timestep_embedding (lib ,op ); 5029 5030const int nth = std::max (1 , std::min (1024 ,dim /2 )); 5031 5032ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5033ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5034ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 5035ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 5036 5037ggml_metal_encoder_dispatch_threadgroups (enc ,ne00 ,1 ,1 ,nth ,1 ,1 ); 5038 5039return 1 ; 5040} 5041 5042int ggml_metal_op_argmax (ggml_metal_op_t ctx ,int idx ) { 5043ggml_tensor * op = ctx -> node (idx ); 5044 5045ggml_metal_library_t lib = ctx -> lib ; 5046ggml_metal_encoder_t enc = ctx -> enc ; 5047 5048GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5049GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5050GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 5051GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 5052 5053ggml_metal_kargs_argmax args = { 5054/*.ne00 = */ ne00 , 5055/*.nb01 = */ nb01 , 5056 }; 5057 5058auto pipeline = ggml_metal_library_get_pipeline_argmax (lib ,op ); 5059 5060const int64_t nrows = ggml_nrows (op -> src [0 ]); 5061 5062int nth = 32 ;// SIMD width 5063while (nth < ne00 && nth * ne01 * ne02 * ne03 < 256 ) { 5064nth *=2 ; 5065 } 5066 5067const size_t smem = pipeline .smem ; 5068 5069ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5070ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5071ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 5072ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 5073 5074ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 5075 5076ggml_metal_encoder_dispatch_threadgroups (enc ,nrows ,1 ,1 ,nth ,1 ,1 ); 5077 5078return 1 ; 5079} 5080 5081int ggml_metal_op_argsort (ggml_metal_op_t ctx ,int idx ) { 5082ggml_tensor * op = ctx -> node (idx ); 5083 5084ggml_metal_library_t lib = ctx -> lib ; 5085ggml_metal_encoder_t enc = ctx -> enc ; 5086 5087GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 5088 5089GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5090GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5091GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 5092GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 5093 5094auto pipeline = ggml_metal_library_get_pipeline_argsort (lib ,op ); 5095 5096// bitonic sort requires the number of elements to be power of 2 5097int nth = 1 ; 5098while (nth < ne00 && 2 * nth <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 5099nth *=2 ; 5100 } 5101 5102const int npr = (ne00 + nth - 1 )/nth ; 5103 5104// Metal kernels require the buffer size to be multiple of 16 bytes 5105// https://developer.apple.com/documentation/metal/mtlcomputecommandencoder/1443142-setthreadgroupmemorylength 5106const size_t smem = GGML_PAD (nth * sizeof (int32_t ),16 ); 5107 5108ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 5109ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 5110 5111ggml_metal_buffer_id bid_tmp = bid_dst ; 5112bid_tmp .offs += ggml_nbytes (op ); 5113 5114if ((int )ceil (std::log (npr ) / std::log (2 )) %2 == 1 ) { 5115 std::swap (bid_dst ,bid_tmp ); 5116 } 5117 5118ggml_metal_kargs_argsort args = { 5119/*.ne00 =*/ ne00 , 5120/*.ne01 =*/ ne01 , 5121/*.ne02 =*/ ne02 , 5122/*.ne03 =*/ ne03 , 5123/*.nb00 =*/ nb00 , 5124/*.nb01 =*/ nb01 , 5125/*.nb02 =*/ nb02 , 5126/*.nb03 =*/ nb03 , 5127/*.ne0 =*/ ne0 , 5128/*.ne1 =*/ ne1 , 5129/*.ne2 =*/ ne2 , 5130/*.ne3 =*/ ne3 , 5131/*.top_k =*/ nth , 5132 }; 5133 5134ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5135ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5136ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 5137ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 5138 5139ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 5140 5141ggml_metal_encoder_dispatch_threadgroups (enc ,npr * ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 5142 5143auto pipeline_merge = ggml_metal_library_get_pipeline_argsort_merge (lib ,op ); 5144 5145int len = nth ; 5146 5147while (len < ne00 ) { 5148ggml_metal_op_concurrency_reset (ctx ); 5149 5150ggml_metal_kargs_argsort_merge args_merge = { 5151/*.ne00 =*/ ne00 , 5152/*.ne01 =*/ ne01 , 5153/*.ne02 =*/ ne02 , 5154/*.ne03 =*/ ne03 , 5155/*.nb00 =*/ nb00 , 5156/*.nb01 =*/ nb01 , 5157/*.nb02 =*/ nb02 , 5158/*.nb03 =*/ nb03 , 5159/*.ne0 =*/ ne0 , 5160/*.ne1 =*/ ne1 , 5161/*.ne2 =*/ ne2 , 5162/*.ne3 =*/ ne3 , 5163/*.top_k =*/ ne00 , 5164/*.len =*/ len , 5165 }; 5166 5167// merges per row 5168const int nm = (ne00 + 2 * len - 1 ) / (2 * len ); 5169 5170const int nth = std::min (512 ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline_merge )); 5171 5172ggml_metal_encoder_set_pipeline (enc ,pipeline_merge ); 5173ggml_metal_encoder_set_bytes (enc ,& args_merge ,sizeof (args_merge ),0 ); 5174ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 5175ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 5176ggml_metal_encoder_set_buffer (enc ,bid_tmp ,3 ); 5177 5178ggml_metal_encoder_dispatch_threadgroups (enc ,nm * ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 5179 5180 std::swap (bid_dst ,bid_tmp ); 5181 5182len <<=1 ; 5183 } 5184 5185return 1 ; 5186} 5187 5188// bitonic-sort + merge fallback: efficient when k is small and there are few rows, 5189// where the single-workgroup-per-row radix-select cannot reach enough parallelism 5190static void ggml_metal_op_top_k_bitonic (ggml_metal_op_t ctx ,int idx ) { 5191ggml_tensor * op = ctx -> node (idx ); 5192 5193ggml_metal_library_t lib = ctx -> lib ; 5194ggml_metal_encoder_t enc = ctx -> enc ; 5195 5196GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 5197 5198GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5199GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5200GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 5201GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 5202 5203auto pipeline = ggml_metal_library_get_pipeline_top_k (lib ,op ); 5204 5205// bitonic sort requires the number of elements to be power of 2 5206int nth = 1 ; 5207while (nth < ne00 && 2 * nth <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 5208nth *=2 ; 5209 } 5210 5211// blocks per row 5212const int npr = (ne00 + nth - 1 )/nth ; 5213 5214const size_t smem = GGML_PAD (nth * sizeof (int32_t ),16 ); 5215 5216ggml_metal_buffer_id bid_src0 = ggml_metal_get_buffer_id (op -> src [0 ]); 5217ggml_metal_buffer_id bid_dst = ggml_metal_get_buffer_id (op ); 5218 5219ggml_metal_buffer_id bid_tmp = bid_dst ; 5220bid_tmp .offs += sizeof (int32_t )* ggml_nelements (op -> src [0 ]); 5221 5222if ((int )ceil (std::log (npr ) / std::log (2 )) %2 == 1 ) { 5223 std::swap (bid_dst ,bid_tmp ); 5224 } 5225 5226const int top_k = ne0 ; 5227 5228ggml_metal_kargs_argsort args = { 5229/*.ne00 =*/ ne00 , 5230/*.ne01 =*/ ne01 , 5231/*.ne02 =*/ ne02 , 5232/*.ne03 =*/ ne03 , 5233/*.nb00 =*/ nb00 , 5234/*.nb01 =*/ nb01 , 5235/*.nb02 =*/ nb02 , 5236/*.nb03 =*/ nb03 , 5237/*.ne0 =*/ ne0 , 5238/*.ne1 =*/ ne1 , 5239/*.ne2 =*/ ne2 , 5240/*.ne3 =*/ ne3 , 5241/*.top_k =*/ std::min (nth ,top_k ),// for each block, keep just the top_k indices 5242 }; 5243 5244if (npr > 1 ) { 5245args .ne0 = (npr - 1 )* args .top_k + std::min (ne00 - (npr - 1 )* nth ,args .top_k ); 5246 } 5247 5248ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5249ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5250ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 5251ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 5252 5253ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 5254 5255ggml_metal_encoder_dispatch_threadgroups (enc ,npr * ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 5256 5257auto pipeline_merge = ggml_metal_library_get_pipeline_top_k_merge (lib ,op ); 5258 5259int len = args .top_k ; 5260 5261while (len < args .ne0 ) { 5262ggml_metal_op_concurrency_reset (ctx ); 5263 5264// merges per row 5265const int nm = (args .ne0 + 2 * len - 1 ) / (2 * len ); 5266 5267const int nth = std::min (512 , std::min (len ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline_merge ))); 5268 5269ggml_metal_kargs_argsort_merge args_merge = { 5270/*.ne00 =*/ ne00 , 5271/*.ne01 =*/ ne01 , 5272/*.ne02 =*/ ne02 , 5273/*.ne03 =*/ ne03 , 5274/*.nb00 =*/ nb00 , 5275/*.nb01 =*/ nb01 , 5276/*.nb02 =*/ nb02 , 5277/*.nb03 =*/ nb03 , 5278/*.ne0 =*/ args .ne0 , 5279/*.ne1 =*/ ne1 , 5280/*.ne2 =*/ ne2 , 5281/*.ne3 =*/ ne3 , 5282/*.top_k =*/ nm == 1 ?top_k :args .ne0 ,// the final merge outputs top_k elements 5283/*.len =*/ len , 5284 }; 5285 5286ggml_metal_encoder_set_pipeline (enc ,pipeline_merge ); 5287ggml_metal_encoder_set_bytes (enc ,& args_merge ,sizeof (args_merge ),0 ); 5288ggml_metal_encoder_set_buffer (enc ,bid_src0 ,1 ); 5289ggml_metal_encoder_set_buffer (enc ,bid_dst ,2 ); 5290ggml_metal_encoder_set_buffer (enc ,bid_tmp ,3 ); 5291 5292ggml_metal_encoder_dispatch_threadgroups (enc ,nm * ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 5293 5294 std::swap (bid_dst ,bid_tmp ); 5295 5296len <<=1 ; 5297 } 5298} 5299 5300// radix-select: one workgroup per row. Maps each float to an order-preserving unsigned 5301// key, finds the k-th largest via 4 radix-8 histogram passes, then compacts the top-k 5302// indices. Fast for large k and/or many rows. 5303static void ggml_metal_op_top_k_radix (ggml_metal_op_t ctx ,int idx ) { 5304ggml_tensor * op = ctx -> node (idx ); 5305 5306ggml_metal_library_t lib = ctx -> lib ; 5307ggml_metal_encoder_t enc = ctx -> enc ; 5308 5309GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 5310 5311GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5312GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5313 5314auto pipeline = ggml_metal_library_get_pipeline_top_k_radix (lib ,op ); 5315 5316// one workgroup per row; radix-select the k-th largest value 5317const int nth = std::min (1024 ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 5318 5319ggml_metal_kargs_top_k args = { 5320/*.ne00 =*/ ne00 , 5321/*.ne01 =*/ ne01 , 5322/*.ne02 =*/ ne02 , 5323/*.ne03 =*/ ne03 , 5324/*.nb01 =*/ nb01 , 5325/*.nb02 =*/ nb02 , 5326/*.nb03 =*/ nb03 , 5327/*.top_k =*/ (int32_t )op -> ne [0 ], 5328 }; 5329 5330// shared memory: 256-entry histogram + bucket/above scalars + output counter 5331const size_t smem_histo = GGML_PAD (256 * sizeof (uint32_t ),16 ); 5332const size_t smem_bucket = GGML_PAD (sizeof (uint32_t ),16 ); 5333const size_t smem_above = GGML_PAD (sizeof (uint32_t ),16 ); 5334const size_t smem_out = GGML_PAD (sizeof (uint32_t ),16 ); 5335 5336ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5337ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5338ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 5339ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 5340 5341ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem_histo ,0 ); 5342ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem_bucket ,1 ); 5343ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem_above ,2 ); 5344ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem_out ,3 ); 5345 5346ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 5347} 5348 5349int ggml_metal_op_top_k (ggml_metal_op_t ctx ,int idx ) { 5350ggml_tensor * op = ctx -> node (idx ); 5351 5352// radix-select has a fixed single-workgroup-per-row cost (~50-60us) that is only 5353// amortized for long rows, many rows, or a large k; otherwise the bitonic path wins 5354const int ncols = op -> src [0 ]-> ne [0 ]; 5355const int k = op -> ne [0 ]; 5356const int nrows = ggml_nrows (op -> src [0 ]); 5357 5358const bool use_radix = 5359ncols > 2048 && (k > 64 || (nrows > 4 && ncols >=8192 )); 5360 5361if (use_radix ) { 5362ggml_metal_op_top_k_radix (ctx ,idx ); 5363 }else { 5364ggml_metal_op_top_k_bitonic (ctx ,idx ); 5365 } 5366 5367return 1 ; 5368} 5369 5370int ggml_metal_op_tri (ggml_metal_op_t ctx ,int idx ) { 5371ggml_tensor * op = ctx -> node (idx ); 5372 5373ggml_metal_library_t lib = ctx -> lib ; 5374ggml_metal_encoder_t enc = ctx -> enc ; 5375 5376GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5377GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5378GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 5379GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 5380 5381ggml_metal_kargs_tri args = { 5382/*.ne00 =*/ ne00 , 5383/*.ne01 =*/ ne01 , 5384/*.ne02 =*/ ne02 , 5385/*.ne03 =*/ ne03 , 5386/*.nb00 =*/ nb00 , 5387/*.nb01 =*/ nb01 , 5388/*.nb02 =*/ nb02 , 5389/*.nb03 =*/ nb03 , 5390/*.ne0 =*/ ne0 , 5391/*.ne1 =*/ ne1 , 5392/*.ne2 =*/ ne2 , 5393/*.ne3 =*/ ne3 , 5394/*.nb0 =*/ nb0 , 5395/*.nb1 =*/ nb1 , 5396/*.nb2 =*/ nb2 , 5397/*.nb3 =*/ nb3 , 5398 }; 5399 5400auto pipeline = ggml_metal_library_get_pipeline_tri (lib ,op ); 5401 5402int nth = 32 ;// SIMD width 5403 5404while (nth < ne00 && nth < ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )) { 5405nth *=2 ; 5406 } 5407 5408nth = std::min (nth ,ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 5409nth = std::min (nth ,ne00 ); 5410 5411ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5412ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5413ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 5414ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),2 ); 5415 5416ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 5417 5418return 1 ; 5419} 5420 5421int ggml_metal_op_opt_step_adamw (ggml_metal_op_t ctx ,int idx ) { 5422ggml_tensor * op = ctx -> node (idx ); 5423 5424ggml_metal_library_t lib = ctx -> lib ; 5425ggml_metal_encoder_t enc = ctx -> enc ; 5426 5427GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5428GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5429GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 5430GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 5431 5432auto pipeline = ggml_metal_library_get_pipeline_opt_step_adamw (lib ,op ); 5433 5434const int64_t np = ggml_nelements (op -> src [0 ]); 5435ggml_metal_kargs_opt_step_adamw args = { 5436/*.np =*/ np , 5437 }; 5438 5439int ida = 0 ; 5440 5441ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5442ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),ida ++ ); 5443ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),ida ++ ); 5444ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),ida ++ ); 5445ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),ida ++ ); 5446ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [3 ]),ida ++ ); 5447ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [4 ]),ida ++ ); 5448 5449const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne0 ); 5450const int64_t n = (np + nth - 1 ) /nth ; 5451 5452ggml_metal_encoder_dispatch_threadgroups (enc ,n ,1 ,1 ,nth ,1 ,1 ); 5453 5454return 1 ; 5455} 5456 5457int ggml_metal_op_opt_step_sgd (ggml_metal_op_t ctx ,int idx ) { 5458ggml_tensor * op = ctx -> node (idx ); 5459 5460ggml_metal_library_t lib = ctx -> lib ; 5461ggml_metal_encoder_t enc = ctx -> enc ; 5462 5463GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5464GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5465GGML_TENSOR_LOCALS (int32_t ,ne ,op ,ne ); 5466GGML_TENSOR_LOCALS (uint64_t ,nb ,op ,nb ); 5467 5468auto pipeline = ggml_metal_library_get_pipeline_opt_step_sgd (lib ,op ); 5469 5470const int64_t np = ggml_nelements (op -> src [0 ]); 5471ggml_metal_kargs_opt_step_sgd args = { 5472/*.np =*/ np , 5473 }; 5474 5475int ida = 0 ; 5476 5477ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5478ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),ida ++ ); 5479ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),ida ++ ); 5480ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),ida ++ ); 5481ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [2 ]),ida ++ ); 5482 5483const int nth = std::min (ggml_metal_pipeline_max_theads_per_threadgroup (pipeline ),ne0 ); 5484const int64_t n = (np + nth - 1 ) /nth ; 5485 5486ggml_metal_encoder_dispatch_threadgroups (enc ,n ,1 ,1 ,nth ,1 ,1 ); 5487 5488return 1 ; 5489} 5490 5491int ggml_metal_op_count_equal (ggml_metal_op_t ctx ,int idx ) { 5492ggml_tensor * op = ctx -> node (idx ); 5493 5494ggml_metal_library_t lib = ctx -> lib ; 5495ggml_metal_encoder_t enc = ctx -> enc ; 5496 5497GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 5498GGML_TENSOR_LOCALS (uint64_t ,nb0 ,op -> src [0 ],nb ); 5499GGML_TENSOR_LOCALS (uint64_t ,nb1 ,op -> src [1 ],nb ); 5500 5501 { 5502ggml_metal_kargs_memset args = {/*.val =*/ 0 }; 5503 5504auto pipeline = ggml_metal_library_get_pipeline_memset (lib ,op ); 5505 5506ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5507ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5508ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),1 ); 5509 5510ggml_metal_encoder_dispatch_threadgroups (enc ,1 ,1 ,1 ,1 ,1 ,1 ); 5511 } 5512 5513ggml_metal_op_concurrency_reset (ctx ); 5514 5515 { 5516ggml_metal_kargs_count_equal args = { 5517/*.ne00 =*/ ne00 , 5518/*.ne01 =*/ ne01 , 5519/*.ne02 =*/ ne02 , 5520/*.ne03 =*/ ne03 , 5521/*.nb00 =*/ nb00 , 5522/*.nb01 =*/ nb01 , 5523/*.nb02 =*/ nb02 , 5524/*.nb03 =*/ nb03 , 5525/*.nb10 =*/ nb10 , 5526/*.nb11 =*/ nb11 , 5527/*.nb12 =*/ nb12 , 5528/*.nb13 =*/ nb13 , 5529 }; 5530 5531auto pipeline = ggml_metal_library_get_pipeline_count_equal (lib ,op ); 5532 5533const size_t smem = pipeline .smem ; 5534 5535const int nth = 32 * pipeline .nsg ; 5536 5537GGML_ASSERT (nth <=ggml_metal_pipeline_max_theads_per_threadgroup (pipeline )); 5538 5539ggml_metal_encoder_set_pipeline (enc ,pipeline ); 5540ggml_metal_encoder_set_bytes (enc ,& args ,sizeof (args ),0 ); 5541ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [0 ]),1 ); 5542ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op -> src [1 ]),2 ); 5543ggml_metal_encoder_set_buffer (enc ,ggml_metal_get_buffer_id (op ),3 ); 5544 5545ggml_metal_encoder_set_threadgroup_memory_size (enc ,smem ,0 ); 5546ggml_metal_encoder_dispatch_threadgroups (enc ,ne01 ,ne02 ,ne03 ,nth ,1 ,1 ); 5547 } 5548 5549return 1 ; 5550}