char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
aac810230
char/aliceai-t5-moe
1#include "ggml-metal-device.h" 2 3#include "ggml-metal-impl.h" 4#include "ggml-metal-tuning.h" 5 6#include "ggml-impl.h" 7 8#include <cassert> 9#include <memory> 10#include <string> 11#include <unordered_map> 12 13struct ggml_metal_device_deleter { 14void operator()(ggml_metal_device_t ctx ) { 15ggml_metal_device_free (ctx ); 16 } 17}; 18 19typedef std::unique_ptr < ggml_metal_device ,ggml_metal_device_deleter > ggml_metal_device_ptr ; 20 21ggml_metal_device_t ggml_metal_device_get (int device ,int n_devices ) { 22static std::vector < ggml_metal_device_ptr > devs ; 23 24devs .emplace_back (ggml_metal_device_init (device ,n_devices )); 25 26return devs .back ().get (); 27} 28 29struct ggml_metal_pipelines { 30 std::unordered_map < std::string ,ggml_metal_pipeline_t > data ; 31}; 32 33ggml_metal_pipelines_t ggml_metal_pipelines_init (void ) { 34ggml_metal_pipelines_t res = new ggml_metal_pipelines (); 35 36return res ; 37} 38 39void ggml_metal_pipelines_free (ggml_metal_pipelines_t ppls ) { 40if (!ppls ) { 41return ; 42 } 43 44for (auto it = ppls -> data .begin ();it != ppls -> data .end ();++ it ) { 45ggml_metal_pipeline_free (it -> second ); 46 } 47 48delete ppls ; 49} 50 51void ggml_metal_pipelines_add (ggml_metal_pipelines_t ppls ,const char * name ,ggml_metal_pipeline_t pipeline ) { 52ppls -> data [name ]= pipeline ; 53} 54 55ggml_metal_pipeline_t ggml_metal_pipelines_get (ggml_metal_pipelines_t ppls ,const char * name ) { 56if (ppls -> data .find (name )== ppls -> data .end ()) { 57return nullptr ; 58 } 59 60return ppls -> data [name ]; 61} 62 63struct ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_base (ggml_metal_library_t lib ,ggml_op op ) { 64char base [256 ]; 65char name [256 ]; 66 67const char * op_str = "undefined" ; 68switch (op ) { 69case GGML_OP_ADD_ID :op_str = "add_id" ;break ; 70default :GGML_ABORT ("fatal error" ); 71 }; 72 73snprintf (base ,256 ,"kernel_%s" ,op_str ); 74snprintf (name ,256 ,"%s" ,base ); 75 76ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 77if (!res .pipeline ) { 78res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 79 } 80 81return res ; 82} 83 84ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_cpy (ggml_metal_library_t lib ,ggml_type tsrc ,ggml_type tdst ) { 85char base [256 ]; 86char name [256 ]; 87 88snprintf (base ,256 ,"kernel_cpy_%s_%s" ,ggml_type_name (tsrc ),ggml_type_name (tdst )); 89snprintf (name ,256 ,"%s" ,base ); 90 91ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 92if (!res .pipeline ) { 93res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 94 } 95 96return res ; 97} 98 99ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_pool_1d (ggml_metal_library_t lib ,const ggml_tensor * op ,ggml_op_pool op_pool ) { 100GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 101GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 && op -> src [0 ]-> type == op -> type ); 102 103const char * pool_str = "undefined" ; 104switch (op_pool ) { 105case GGML_OP_POOL_AVG :pool_str = "avg" ;break ; 106case GGML_OP_POOL_MAX :pool_str = "max" ;break ; 107default :GGML_ASSERT (false&& "not implemented" ); 108 }; 109 110char base [256 ]; 111char name [256 ]; 112 113snprintf (base ,sizeof (base ),"kernel_pool_1d_%s_%s" ,pool_str ,ggml_type_name (op -> src [0 ]-> type )); 114snprintf (name ,sizeof (name ),"%s" ,base ); 115 116ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 117if (!res .pipeline ) { 118res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 119 } 120 121return res ; 122} 123 124ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_pool_2d (ggml_metal_library_t lib ,const ggml_tensor * op ,ggml_op_pool op_pool ) { 125GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 126GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 && op -> src [0 ]-> type == op -> type ); 127 128const char * pool_str = "undefined" ; 129switch (op_pool ) { 130case GGML_OP_POOL_AVG :pool_str = "avg" ;break ; 131case GGML_OP_POOL_MAX :pool_str = "max" ;break ; 132default :GGML_ASSERT (false&& "not implemented" ); 133 }; 134 135char base [256 ]; 136char name [256 ]; 137 138snprintf (base ,256 ,"kernel_pool_2d_%s_%s" ,pool_str ,ggml_type_name (op -> src [0 ]-> type )); 139snprintf (name ,256 ,"%s" ,base ); 140 141ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 142if (!res .pipeline ) { 143res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 144 } 145 146return res ; 147} 148 149ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_get_rows (ggml_metal_library_t lib ,ggml_type tsrc ) { 150char base [256 ]; 151char name [256 ]; 152 153snprintf (base ,256 ,"kernel_get_rows_%s" ,ggml_type_name (tsrc )); 154snprintf (name ,256 ,"%s" ,base ); 155 156ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 157if (!res .pipeline ) { 158res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 159 } 160 161return res ; 162} 163 164ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_set_rows (ggml_metal_library_t lib ,const ggml_tensor * op ) { 165char base [256 ]; 166char name [256 ]; 167 168const auto tsrc = op -> src [0 ]-> type ; 169const auto tidx = op -> src [1 ]-> type ; 170const auto tdst = op -> type ; 171 172snprintf (base ,256 ,"kernel_set_rows_%s_%s_%s" ,ggml_type_name (tsrc ),ggml_type_name (tidx ),ggml_type_name (tdst )); 173snprintf (name ,256 ,"%s" ,base ); 174 175ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 176if (!res .pipeline ) { 177res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 178 } 179 180return res ; 181} 182 183ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_diag (ggml_metal_library_t lib ,const ggml_tensor * op ) { 184char base [256 ]; 185char name [256 ]; 186 187const int n = op -> src [0 ]-> ne [0 ]; 188 189snprintf (base ,256 ,"kernel_diag_%s" ,ggml_type_name (op -> src [0 ]-> type )); 190snprintf (name ,256 ,"%s_n=%d" ,base ,n ); 191 192ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 193if (!res .pipeline ) { 194res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 195 } 196 197res .nsg = 1 ; 198res .smem = 0 ; 199 200return res ; 201} 202 203ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_repeat (ggml_metal_library_t lib ,ggml_type tsrc ) { 204char base [256 ]; 205char name [256 ]; 206 207snprintf (base ,256 ,"kernel_repeat_%s" ,ggml_type_name (tsrc )); 208snprintf (name ,256 ,"%s" ,base ); 209 210ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 211if (!res .pipeline ) { 212res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 213 } 214 215return res ; 216} 217 218ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_concat (ggml_metal_library_t lib ,ggml_type tsrc ) { 219char base [256 ]; 220char name [256 ]; 221 222snprintf (base ,256 ,"kernel_concat_%s" ,ggml_type_name (tsrc )); 223snprintf (name ,256 ,"%s" ,base ); 224 225ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 226if (!res .pipeline ) { 227res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 228 } 229 230return res ; 231} 232 233ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_unary (ggml_metal_library_t lib ,const ggml_tensor * op ) { 234char base [256 ]; 235char name [256 ]; 236 237int op_num = -1 ; 238 239switch (op -> op ) { 240case GGML_OP_SCALE :op_num = OP_UNARY_NUM_SCALE ;break ; 241case GGML_OP_FILL :op_num = OP_UNARY_NUM_FILL ;break ; 242case GGML_OP_CLAMP :op_num = OP_UNARY_NUM_CLAMP ;break ; 243case GGML_OP_SQR :op_num = OP_UNARY_NUM_SQR ;break ; 244case GGML_OP_SQRT :op_num = OP_UNARY_NUM_SQRT ;break ; 245case GGML_OP_SIN :op_num = OP_UNARY_NUM_SIN ;break ; 246case GGML_OP_COS :op_num = OP_UNARY_NUM_COS ;break ; 247case GGML_OP_LOG :op_num = OP_UNARY_NUM_LOG ;break ; 248case GGML_OP_LEAKY_RELU :op_num = OP_UNARY_NUM_LEAKY_RELU ;break ; 249case GGML_OP_UNARY : 250switch (ggml_get_unary_op (op )) { 251case GGML_UNARY_OP_TANH :op_num = OP_UNARY_NUM_TANH ;break ; 252case GGML_UNARY_OP_RELU :op_num = OP_UNARY_NUM_RELU ;break ; 253case GGML_UNARY_OP_SIGMOID :op_num = OP_UNARY_NUM_SIGMOID ;break ; 254case GGML_UNARY_OP_GELU :op_num = OP_UNARY_NUM_GELU ;break ; 255case GGML_UNARY_OP_GELU_ERF :op_num = OP_UNARY_NUM_GELU_ERF ;break ; 256case GGML_UNARY_OP_GELU_QUICK :op_num = OP_UNARY_NUM_GELU_QUICK ;break ; 257case GGML_UNARY_OP_SILU :op_num = OP_UNARY_NUM_SILU ;break ; 258case GGML_UNARY_OP_ELU :op_num = OP_UNARY_NUM_ELU ;break ; 259case GGML_UNARY_OP_NEG :op_num = OP_UNARY_NUM_NEG ;break ; 260case GGML_UNARY_OP_ABS :op_num = OP_UNARY_NUM_ABS ;break ; 261case GGML_UNARY_OP_SGN :op_num = OP_UNARY_NUM_SGN ;break ; 262case GGML_UNARY_OP_STEP :op_num = OP_UNARY_NUM_STEP ;break ; 263case GGML_UNARY_OP_HARDSWISH :op_num = OP_UNARY_NUM_HARDSWISH ;break ; 264case GGML_UNARY_OP_HARDSIGMOID :op_num = OP_UNARY_NUM_HARDSIGMOID ;break ; 265case GGML_UNARY_OP_EXP :op_num = OP_UNARY_NUM_EXP ;break ; 266case GGML_UNARY_OP_SOFTPLUS :op_num = OP_UNARY_NUM_SOFTPLUS ;break ; 267case GGML_UNARY_OP_EXPM1 :op_num = OP_UNARY_NUM_EXPM1 ;break ; 268case GGML_UNARY_OP_FLOOR :op_num = OP_UNARY_NUM_FLOOR ;break ; 269case GGML_UNARY_OP_CEIL :op_num = OP_UNARY_NUM_CEIL ;break ; 270case GGML_UNARY_OP_ROUND :op_num = OP_UNARY_NUM_ROUND ;break ; 271case GGML_UNARY_OP_TRUNC :op_num = OP_UNARY_NUM_TRUNC ;break ; 272case GGML_UNARY_OP_XIELU :op_num = OP_UNARY_NUM_XIELU ;break ; 273default :GGML_ABORT ("fatal error" ); 274 }break ; 275default :GGML_ABORT ("fatal error" ); 276 }; 277 278const char * t0_str = ggml_type_name (op -> src [0 ]-> type ); 279const char * t_str = ggml_type_name (op -> type ); 280 281const bool is_c4 = op -> src [0 ]-> ne [0 ] %4 == 0 ; 282const bool is_cnt = ggml_is_contiguous (op -> src [0 ])&& ggml_nelements (op )< 32768 ; 283 284snprintf (base ,256 ,"kernel_unary_%s_%s%s" ,t0_str ,t_str ,is_c4 ?"_4" :"" ); 285snprintf (name ,256 ,"%s_op=%d_cnt=%d" ,base ,op_num ,is_cnt ); 286 287ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 288if (!res .pipeline ) { 289ggml_metal_cv_t cv = ggml_metal_cv_init (); 290 291ggml_metal_cv_set_int16 (cv ,op_num ,FC_UNARY + 0 ); 292ggml_metal_cv_set_bool (cv ,is_cnt ,FC_UNARY + 1 ); 293 294res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 295 296ggml_metal_cv_free (cv ); 297 } 298 299res .c4 = is_c4 ; 300res .cnt = is_cnt ; 301 302return res ; 303} 304 305ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_glu (ggml_metal_library_t lib ,const ggml_tensor * op ) { 306GGML_ASSERT (ggml_is_contiguous_1 (op -> src [0 ])); 307 308char base [256 ]; 309char name [256 ]; 310 311const char * op_str = "undefined" ; 312switch (op -> op ) { 313case GGML_OP_GLU : 314switch (ggml_get_glu_op (op )) { 315case GGML_GLU_OP_REGLU :op_str = "reglu" ;break ; 316case GGML_GLU_OP_GEGLU :op_str = "geglu" ;break ; 317case GGML_GLU_OP_SWIGLU :op_str = "swiglu" ;break ; 318case GGML_GLU_OP_SWIGLU_OAI :op_str = "swiglu_oai" ;break ; 319case GGML_GLU_OP_GEGLU_ERF :op_str = "geglu_erf" ;break ; 320case GGML_GLU_OP_GEGLU_QUICK :op_str = "geglu_quick" ;break ; 321case GGML_GLU_OP_SWIGLU_CLAMP :op_str = "swiglu_clamp" ;break ; 322default :GGML_ABORT ("fatal error" ); 323 }break ; 324default :GGML_ABORT ("fatal error" ); 325 }; 326 327snprintf (base ,256 ,"kernel_%s_%s" ,op_str ,ggml_type_name (op -> src [0 ]-> type )); 328snprintf (name ,256 ,"%s" ,base ); 329 330ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 331if (!res .pipeline ) { 332res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 333 } 334 335return res ; 336} 337 338ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_sum (ggml_metal_library_t lib ,const ggml_tensor * op ) { 339assert (op -> op == GGML_OP_SUM ); 340 341char base [256 ]; 342char name [256 ]; 343 344snprintf (base ,256 ,"kernel_op_sum_%s" ,ggml_type_name (op -> src [0 ]-> type )); 345snprintf (name ,256 ,"%s" ,base ); 346 347ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 348if (!res .pipeline ) { 349res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 350 } 351 352return res ; 353} 354 355ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_sum_rows (ggml_metal_library_t lib ,const ggml_tensor * op ) { 356GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 357 358char base [256 ]; 359char name [256 ]; 360 361int op_num = -1 ; 362 363switch (op -> op ) { 364case GGML_OP_SUM_ROWS :op_num = OP_SUM_ROWS_NUM_SUM_ROWS ;break ; 365case GGML_OP_MEAN :op_num = OP_SUM_ROWS_NUM_MEAN ;break ; 366default :GGML_ABORT ("fatal error" ); 367 }; 368 369const char * t0_str = ggml_type_name (op -> src [0 ]-> type ); 370const char * t_str = ggml_type_name (op -> type ); 371 372const bool is_c4 = op -> src [0 ]-> ne [0 ] %4 == 0 ; 373 374snprintf (base ,256 ,"kernel_sum_rows_%s_%s%s" ,t0_str ,t_str ,is_c4 ?"_4" :"" ); 375snprintf (name ,256 ,"%s_op=%d" ,base ,op_num ); 376 377ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 378if (!res .pipeline ) { 379ggml_metal_cv_t cv = ggml_metal_cv_init (); 380 381ggml_metal_cv_set_int16 (cv ,op_num ,FC_SUM_ROWS + 0 ); 382 383res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 384 385ggml_metal_cv_free (cv ); 386 } 387 388res .smem = 32 * sizeof (float ); 389 390if (is_c4 ) { 391res .smem *=4 ; 392 } 393 394res .c4 = is_c4 ; 395 396return res ; 397} 398 399ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_cumsum_blk (ggml_metal_library_t lib ,const ggml_tensor * op ) { 400GGML_ASSERT (op -> op == GGML_OP_CUMSUM ); 401 402char base [256 ]; 403char name [256 ]; 404 405snprintf (base ,256 ,"kernel_cumsum_blk_%s" ,ggml_type_name (op -> src [0 ]-> type )); 406snprintf (name ,256 ,"%s" ,base ); 407 408ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 409if (!res .pipeline ) { 410res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 411 } 412 413return res ; 414} 415 416ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_cumsum_add (ggml_metal_library_t lib ,const ggml_tensor * op ) { 417GGML_ASSERT (op -> op == GGML_OP_CUMSUM ); 418 419char base [256 ]; 420char name [256 ]; 421 422snprintf (base ,256 ,"kernel_cumsum_add_%s" ,ggml_type_name (op -> src [0 ]-> type )); 423snprintf (name ,256 ,"%s" ,base ); 424 425ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 426if (!res .pipeline ) { 427res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 428 } 429 430return res ; 431} 432 433ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_tri (ggml_metal_library_t lib ,const ggml_tensor * op ) { 434GGML_ASSERT (op -> op == GGML_OP_TRI ); 435GGML_ASSERT (op -> src [0 ]-> nb [0 ]== ggml_type_size (op -> src [0 ]-> type )); 436 437char base [256 ]; 438char name [256 ]; 439 440const char * op_str = "tri" ; 441const int ttype = op -> op_params [0 ]; 442 443snprintf (base ,256 ,"kernel_%s_%s_%d" ,op_str ,ggml_type_name (op -> src [0 ]-> type ),ttype ); 444 445snprintf (name ,256 ,"%s" ,base ); 446 447ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 448if (!res .pipeline ) { 449res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 450 } 451 452return res ; 453} 454 455ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_soft_max (ggml_metal_library_t lib ,const ggml_tensor * op ) { 456GGML_ASSERT (!op -> src [1 ]|| op -> src [1 ]-> type == GGML_TYPE_F16 || op -> src [1 ]-> type == GGML_TYPE_F32 ); 457 458char base [256 ]; 459char name [256 ]; 460 461const char * suffix = "" ; 462 463if (op -> src [0 ]-> ne [0 ] %4 == 0 ) { 464suffix = "_4" ; 465 } 466 467const ggml_type tsrc1 = op -> src [1 ] ?op -> src [1 ]-> type :GGML_TYPE_F32 ; 468 469snprintf (base ,256 ,"kernel_soft_max_%s%s" ,ggml_type_name (tsrc1 ),suffix ); 470snprintf (name ,256 ,"%s" ,base ); 471 472ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 473if (!res .pipeline ) { 474res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 475 } 476 477res .smem = 32 * sizeof (float ); 478 479return res ; 480} 481 482ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_lightning_indexer ( 483ggml_metal_library_t lib , 484const ggml_tensor * op ) { 485GGML_ASSERT (op -> op == GGML_OP_LIGHTNING_INDEXER ); 486 487char name [256 ]; 488 489snprintf (name ,256 ,"kernel_lightning_indexer_%s" ,ggml_type_name (op -> src [1 ]-> type )); 490 491ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 492if (!res .pipeline ) { 493res = ggml_metal_library_compile_pipeline (lib ,name ,name ,nullptr ); 494 } 495 496return res ; 497} 498 499ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_dsv4_hc (ggml_metal_library_t lib ,ggml_op op ) { 500const char * name = nullptr ; 501 502switch (op ) { 503case GGML_OP_DSV4_HC_COMB :name = "kernel_dsv4_hc_comb_f32" ;break ; 504case GGML_OP_DSV4_HC_PRE :name = "kernel_dsv4_hc_pre_f32" ;break ; 505case GGML_OP_DSV4_HC_POST :name = "kernel_dsv4_hc_post_f32" ;break ; 506default :GGML_ABORT ("fatal error" ); 507 } 508 509ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 510if (!res .pipeline ) { 511res = ggml_metal_library_compile_pipeline (lib ,name ,name ,nullptr ); 512 } 513 514return res ; 515} 516 517ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_ssm_conv (ggml_metal_library_t lib ,const ggml_tensor * op ) { 518GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 ); 519GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 520 521GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 522GGML_ASSERT (ggml_is_contiguous (op -> src [1 ])); 523 524char base [256 ]; 525char name [256 ]; 526 527const char * suffix = "" ; 528 529if (op -> src [1 ]-> ne [0 ] %4 == 0 ) { 530suffix = "_4" ; 531 } 532 533snprintf (base ,256 ,"kernel_ssm_conv_%s_%s%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> src [1 ]-> type ),suffix ); 534snprintf (name ,256 ,"%s" ,base ); 535 536ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 537if (!res .pipeline ) { 538res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 539 } 540 541return res ; 542} 543 544ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_ssm_conv_batched (ggml_metal_library_t lib ,const ggml_tensor * op ,int ssm_conv_bs ) { 545GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 ); 546GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 547 548GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 549GGML_ASSERT (ggml_is_contiguous (op -> src [1 ])); 550 551char base [256 ]; 552char name [256 ]; 553 554const char * suffix = "" ; 555if (op -> src [1 ]-> ne [0 ] %4 == 0 ) { 556suffix = "_4" ; 557 } 558 559snprintf (base ,256 ,"kernel_ssm_conv_%s_%s_batched%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> src [1 ]-> type ),suffix ); 560snprintf (name ,256 ,"%s_ssm_conv_bs=%d" ,base ,ssm_conv_bs ); 561 562ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 563if (!res .pipeline ) { 564ggml_metal_cv_t cv = ggml_metal_cv_init (); 565 566ggml_metal_cv_set_int16 (cv ,ssm_conv_bs ,FC_SSM_CONV + 0 ); 567 568res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 569 570ggml_metal_cv_free (cv ); 571 } 572 573return res ; 574} 575 576ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_ssm_scan (ggml_metal_library_t lib ,const ggml_tensor * op ,bool tail ) { 577GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 578 579char base [256 ]; 580char name [256 ]; 581 582const int nsg = (ne00 + 31 )/32 ; 583 584snprintf (base ,256 ,"kernel_ssm_scan_%s%s" ,ggml_type_name (op -> src [0 ]-> type ),tail ?"_tail" :"" ); 585snprintf (name ,256 ,"%s_nsg=%d" ,base ,nsg ); 586 587ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 588if (!res .pipeline ) { 589res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 590 } 591 592// Shared memory layout: 593// - sgptg * NW floats for partial sums (nsg * 32) 594// - sgptg floats for shared_x_dt (nsg) 595// - sgptg floats for shared_dA (nsg) 596// Total: nsg * (32 + 2) floats 597res .smem = GGML_PAD ((32 + 2 )* sizeof (float )* nsg ,16 ); 598 599return res ; 600} 601 602ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_ssm_scan_ssd_mma (ggml_metal_library_t lib ,const ggml_tensor * op ) { 603char base [256 ]; 604char name [256 ]; 605 606snprintf (base ,256 ,"kernel_ssm_scan_ssd_mma_%s" ,ggml_type_name (op -> src [0 ]-> type )); 607snprintf (name ,256 ,"%s" ,base ); 608 609ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 610if (!res .pipeline ) { 611res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 612 } 613 614// acs/exp(acs)/state-decay vectors + dtX + SAM rows + two 8x8 tiles per simdgroup 615res .smem = (3 * OP_SSM_SCAN_SSD_CS + 616OP_SSM_SCAN_SSD_CS * OP_SSM_SCAN_SSD_HD + 617OP_SSM_SCAN_SSD_NSG * 8 * OP_SSM_SCAN_SSD_CS + 618OP_SSM_SCAN_SSD_NSG * 2 * 8 * 8 )* sizeof (float ); 619 620return res ; 621} 622 623ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_rwkv (ggml_metal_library_t lib ,const ggml_tensor * op ) { 624char base [256 ]; 625char name [256 ]; 626 627const int64_t C = op -> ne [0 ]; 628const int64_t H = op -> src [0 ]-> ne [1 ]; 629 630switch (op -> op ) { 631case GGML_OP_RWKV_WKV6 : 632 { 633GGML_ASSERT (op -> src [5 ]-> type == GGML_TYPE_F32 ); 634GGML_ASSERT (C %H == 0 ); 635GGML_ASSERT (C /H == 64 ); 636 637snprintf (base ,256 ,"kernel_rwkv_wkv6_%s" ,ggml_type_name (op -> src [0 ]-> type )); 638 }break ; 639case GGML_OP_RWKV_WKV7 : 640 { 641GGML_ASSERT (op -> src [6 ]-> type == GGML_TYPE_F32 ); 642GGML_ASSERT (C %H == 0 ); 643GGML_ASSERT (C /H == 64 ); 644 645snprintf (base ,256 ,"kernel_rwkv_wkv7_%s" ,ggml_type_name (op -> src [0 ]-> type )); 646 }break ; 647default : 648GGML_ABORT ("fatal error" ); 649 } 650 651snprintf (name ,256 ,"%s" ,base ); 652 653ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 654if (!res .pipeline ) { 655res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 656 } 657 658return res ; 659} 660 661ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_gated_delta_net (ggml_metal_library_t lib ,const ggml_tensor * op ) { 662char base [256 ]; 663char name [256 ]; 664 665// v is src[2], dimensions: S_v = ne[0], H = ne[1] 666const int ne20 = op -> src [2 ]-> ne [0 ];// S_v 667const int ne21 = op -> src [2 ]-> ne [1 ];// H 668const int ne30 = op -> src [3 ]-> ne [0 ];// G 669// state is src[5], 4D [S_v, S_v, H_v, n_seqs] (s0 only); K is op param 0. 670const int K = ggml_get_op_params_i32 (op ,0 ); 671 672const int nsg = op -> src [2 ]-> ne [0 ]/32 ; 673 674GGML_ASSERT (op -> src [5 ]-> type == GGML_TYPE_F32 ); 675GGML_ASSERT (op -> ne [0 ]== ne20 * ne21 ); 676GGML_ASSERT (ne20 %32 == 0 ); 677 678snprintf (base ,256 ,"kernel_gated_delta_net_%s_%d" ,ggml_type_name (op -> src [0 ]-> type ),nsg ); 679snprintf (name ,256 ,"%s_ne20=%d_ne30=%d_K=%d" ,base ,ne20 ,ne30 ,K ); 680 681ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 682if (!res .pipeline ) { 683ggml_metal_cv_t cv = ggml_metal_cv_init (); 684 685ggml_metal_cv_set_int16 (cv ,ne20 ,FC_GATED_DELTA_NET + 0 ); 686ggml_metal_cv_set_int16 (cv ,ne30 ,FC_GATED_DELTA_NET + 1 ); 687ggml_metal_cv_set_int16 (cv ,K ,FC_GATED_DELTA_NET + 2 ); 688 689res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 690 691ggml_metal_cv_free (cv ); 692 } 693 694res .nsg = nsg ; 695 696return res ; 697} 698 699ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_solve_tri (ggml_metal_library_t lib ,const ggml_tensor * op ) { 700char base [256 ]; 701char name [256 ]; 702 703const int nsg = 8 ; 704const int n = op -> src [1 ]-> ne [1 ]; 705const int k = op -> src [1 ]-> ne [0 ]; 706 707snprintf (base ,256 ,"kernel_solve_tri_%s" ,ggml_type_name (op -> src [0 ]-> type )); 708snprintf (name ,256 ,"%s_nsg=%d_n=%d_k=%d" ,base ,nsg ,n ,k ); 709 710ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 711if (!res .pipeline ) { 712ggml_metal_cv_t cv = ggml_metal_cv_init (); 713 714ggml_metal_cv_set_int16 (cv ,nsg ,FC_SOLVE_TRI + 0 ); 715ggml_metal_cv_set_int16 (cv ,n ,FC_SOLVE_TRI + 1 ); 716ggml_metal_cv_set_int16 (cv ,k ,FC_SOLVE_TRI + 2 ); 717 718res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 719 720ggml_metal_cv_free (cv ); 721 } 722 723res .nsg = nsg ; 724res .smem = GGML_PAD (GGML_PAD (n ,32 )* nsg * sizeof (float ),16 ); 725 726return res ; 727} 728 729ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_mul_mv_ext (ggml_metal_library_t lib ,const ggml_tensor * op ,int nsg ,int nxpsg ,int r1ptg ) { 730char base [256 ]; 731char name [256 ]; 732 733const ggml_type tsrc0 = op -> src [0 ]-> type ; 734const ggml_type tsrc1 = op -> src [1 ]-> type ; 735const int ne12 = op -> src [1 ]-> ne [2 ]; 736const int r2 = ne12 /op -> src [0 ]-> ne [2 ]; 737const int r3 = op -> src [1 ]-> ne [3 ] /op -> src [0 ]-> ne [3 ]; 738 739GGML_ASSERT (ne12 <=INT16_MAX && r2 <=INT16_MAX && r3 <=INT16_MAX ); 740 741snprintf (base ,256 ,"kernel_mul_mv_ext_%s_%s_r1_%d" ,ggml_type_name (tsrc0 ),ggml_type_name (tsrc1 ),r1ptg ); 742snprintf (name ,256 ,"%s_nsg=%d_nxpsg=%d_ne12=%d_r2=%d_r3=%d" ,base ,nsg ,nxpsg ,ne12 ,r2 ,r3 ); 743 744ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 745if (!res .pipeline ) { 746ggml_metal_cv_t cv = ggml_metal_cv_init (); 747 748ggml_metal_cv_set_int16 (cv ,nsg ,FC_MUL_MV + 0 ); 749ggml_metal_cv_set_int16 (cv ,nxpsg ,FC_MUL_MV + 1 ); 750ggml_metal_cv_set_int16 (cv , (int16_t )ne12 ,FC_MUL_MV + 2 ); 751ggml_metal_cv_set_int16 (cv , (int16_t )r2 ,FC_MUL_MV + 3 ); 752ggml_metal_cv_set_int16 (cv , (int16_t )r3 ,FC_MUL_MV + 4 ); 753 754res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 755 756ggml_metal_cv_free (cv ); 757 } 758 759return res ; 760} 761 762ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_mul_mm (ggml_metal_library_t lib ,const ggml_tensor * op ) { 763char base [256 ]; 764char name [256 ]; 765 766const ggml_type tsrc0 = op -> src [0 ]-> type ; 767const ggml_type tsrc1 = op -> src [1 ]-> type ; 768 769const bool bc_inp = op -> src [0 ]-> ne [0 ] %32 != 0 ; 770 771constexpr int NRA = SZ_SIMDGROUP * N_MM_BLOCK_Y * N_MM_SIMD_GROUP_Y ; 772constexpr int NRB = SZ_SIMDGROUP * N_MM_BLOCK_X * N_MM_SIMD_GROUP_X ; 773 774const bool has_tensor = ggml_metal_device_get_props (ggml_metal_library_get_device (lib ))-> has_tensor ; 775 776const bool bc_out = has_tensor 777 ? (op -> ne [0 ] %NRA != 0 || op -> ne [1 ] %NRB != 0 ) 778 : (op -> ne [0 ] %64 != 0 || op -> ne [1 ] %32 != 0 ); 779 780GGML_ASSERT (op -> src [1 ]-> ne [2 ] <=INT16_MAX && op -> src [1 ]-> ne [3 ] <=INT16_MAX ); 781const int16_t ne12 = (int16_t )op -> src [1 ]-> ne [2 ]; 782const int16_t ne13 = (int16_t )op -> src [1 ]-> ne [3 ]; 783const int16_t r2 = (int16_t ) (ne12 /op -> src [0 ]-> ne [2 ]); 784const int16_t r3 = (int16_t ) (ne13 /op -> src [0 ]-> ne [3 ]); 785 786snprintf (base ,256 ,"kernel_mul_mm_%s_%s" ,ggml_type_name (tsrc0 ),ggml_type_name (tsrc1 )); 787snprintf (name ,256 ,"%s_bci=%d_bco=%d_ne12=%d_ne13=%d_r2=%d_r3=%d" , 788base ,bc_inp ,bc_out ,ne12 ,ne13 ,r2 ,r3 ); 789 790ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 791if (!res .pipeline ) { 792ggml_metal_cv_t cv = ggml_metal_cv_init (); 793 794ggml_metal_cv_set_bool (cv ,bc_inp ,FC_MUL_MM + 0 ); 795ggml_metal_cv_set_bool (cv ,bc_out ,FC_MUL_MM + 1 ); 796ggml_metal_cv_set_int16 (cv ,ne12 ,FC_MUL_MM + 2 ); 797ggml_metal_cv_set_int16 (cv ,ne13 ,FC_MUL_MM + 3 ); 798ggml_metal_cv_set_int16 (cv ,r2 ,FC_MUL_MM + 4 ); 799ggml_metal_cv_set_int16 (cv ,r3 ,FC_MUL_MM + 5 ); 800 801res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 802 803ggml_metal_cv_free (cv ); 804 } 805 806if (has_tensor ) { 807res .nr0 = NRA ; 808res .nr1 = NRB ; 809 810const size_t smem_a = NRA * N_MM_NK_TOTAL * sizeof (ggml_fp16_t ); 811res .smem = smem_a ; 812 }else { 813res .nr0 = 64 ; 814res .nr1 = 32 ; 815 816res .smem = bc_out ?8192 : (4096 + 2048 ); 817 } 818 819res .nsg = N_MM_SIMD_GROUP_X * N_MM_SIMD_GROUP_Y ; 820 821return res ; 822} 823 824ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_mul_mv (ggml_metal_library_t lib ,const ggml_tensor * op ) { 825GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 826GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 827 828char base [256 ]; 829char name [256 ]; 830 831int nsg = 0 ;// number of simdgroups 832int nr0 = 0 ;// number of src0 rows per simdgroup 833int nr1 = 1 ;// number of src1 rows per threadgroup 834 835size_t smem = 0 ;// shared memory 836 837const ggml_type tsrc0 = op -> src [0 ]-> type ; 838const ggml_type tsrc1 = op -> src [1 ]-> type ; 839 840const char * suffix = "" ; 841 842bool split = false; 843 844// use custom matrix x vector kernel 845switch (tsrc0 ) { 846case GGML_TYPE_F32 : 847case GGML_TYPE_F16 : 848case GGML_TYPE_BF16 : 849 { 850if (ne00 < 32 ) { 851nsg = 1 ; 852nr0 = 32 ; 853nr1 = 1 ; 854suffix = "_short" ; 855 }else { 856nsg = std::min (4 , (ne00 + 127 ) /128 ); 857nr0 = 2 ; 858nr1 = 1 ; 859smem = 32 * sizeof (float )* nr0 ; 860suffix = ne00 %4 == 0 ?"_4" :"" ; 861 } 862 }break ; 863case GGML_TYPE_Q1_0 : 864 { 865nsg = N_SG_Q1_0 ; 866nr0 = N_R0_Q1_0 ; 867 }break ; 868case GGML_TYPE_Q2_0 : 869 { 870nsg = N_SG_Q2_0 ; 871nr0 = N_R0_Q2_0 ; 872 }break ; 873case GGML_TYPE_Q4_0 : 874 { 875nsg = N_SG_Q4_0 ; 876nr0 = N_R0_Q4_0 ; 877 }break ; 878case GGML_TYPE_Q4_1 : 879 { 880nsg = N_SG_Q4_1 ; 881nr0 = N_R0_Q4_1 ; 882 }break ; 883case GGML_TYPE_Q5_0 : 884 { 885nsg = N_SG_Q5_0 ; 886nr0 = N_R0_Q5_0 ; 887 }break ; 888case GGML_TYPE_Q5_1 : 889 { 890nsg = N_SG_Q5_1 ; 891nr0 = N_R0_Q5_1 ; 892 }break ; 893case GGML_TYPE_Q8_0 : 894 { 895nsg = N_SG_Q8_0 ; 896nr0 = N_R0_Q8_0 ; 897smem = 32 * sizeof (float )* N_R0_Q8_0 ; 898 }break ; 899case GGML_TYPE_MXFP4 : 900 { 901nsg = N_SG_MXFP4 ; 902nr0 = N_R0_MXFP4 ; 903smem = 32 * sizeof (float ); 904 }break ; 905case GGML_TYPE_Q2_K : 906 { 907nsg = N_SG_Q2_K ; 908nr0 = N_R0_Q2_K ; 909 }break ; 910case GGML_TYPE_Q3_K : 911 { 912nsg = N_SG_Q3_K ; 913nr0 = N_R0_Q3_K ; 914 }break ; 915case GGML_TYPE_Q4_K : 916 { 917nsg = N_SG_Q4_K ; 918nr0 = N_R0_Q4_K ; 919 }break ; 920case GGML_TYPE_Q5_K : 921 { 922nsg = N_SG_Q5_K ; 923nr0 = N_R0_Q5_K ; 924 }break ; 925case GGML_TYPE_Q6_K : 926 { 927nsg = N_SG_Q6_K ; 928nr0 = N_R0_Q6_K ; 929 }break ; 930case GGML_TYPE_IQ2_XXS : 931 { 932nsg = N_SG_IQ2_XXS ; 933nr0 = N_R0_IQ2_XXS ; 934smem = 256 * 8 + 128 ; 935 936const int nb32 = ne00 /32 ; 937if (nb32 < 32 && (32 %nb32 )== 0 ) { 938nr0 = N_R0_IQ2_XXS_SPLIT ; 939split = true; 940 } 941 }break ; 942case GGML_TYPE_IQ2_XS : 943 { 944nsg = N_SG_IQ2_XS ; 945nr0 = N_R0_IQ2_XS ; 946smem = 512 * 8 + 128 ; 947 948const int nb32 = ne00 /32 ; 949if (nb32 < 32 && (32 %nb32 )== 0 ) { 950nr0 = N_R0_IQ2_XS_SPLIT ; 951split = true; 952 } 953 }break ; 954case GGML_TYPE_IQ3_XXS : 955 { 956nsg = N_SG_IQ3_XXS ; 957nr0 = N_R0_IQ3_XXS ; 958smem = 256 * 4 + 128 ; 959 960// split the rows across threads when there are fewer than 32 chunks per row 961const int nb32 = ne00 /32 ; 962if (nb32 < 32 && (32 %nb32 )== 0 ) { 963nr0 = N_R0_IQ3_XXS_SPLIT ; 964split = true; 965 } 966 }break ; 967case GGML_TYPE_IQ3_S : 968 { 969nsg = N_SG_IQ3_S ; 970nr0 = N_R0_IQ3_S ; 971smem = 512 * 4 ; 972 973const int nb32 = ne00 /32 ; 974if (nb32 < 32 && (32 %nb32 )== 0 ) { 975nr0 = N_R0_IQ3_S_SPLIT ; 976split = true; 977 } 978 }break ; 979case GGML_TYPE_IQ2_S : 980 { 981nsg = N_SG_IQ2_S ; 982nr0 = N_R0_IQ2_S ; 983 984const int nb32 = ne00 /32 ; 985if (nb32 < 32 && (32 %nb32 )== 0 ) { 986nr0 = N_R0_IQ2_S_SPLIT ; 987split = true; 988 } 989 }break ; 990case GGML_TYPE_IQ1_S : 991 { 992nsg = N_SG_IQ1_S ; 993nr0 = N_R0_IQ1_S ; 994 995const int nb32 = ne00 /32 ; 996if (nb32 < 32 && (32 %nb32 )== 0 ) { 997nr0 = N_R0_IQ1_S_SPLIT ; 998split = true; 999 } 1000 }break ; 1001case GGML_TYPE_IQ1_M : 1002 { 1003nsg = N_SG_IQ1_M ; 1004nr0 = N_R0_IQ1_M ; 1005 1006const int nb32 = ne00 /32 ; 1007if (nb32 < 32 && (32 %nb32 )== 0 ) { 1008nr0 = N_R0_IQ1_M_SPLIT ; 1009split = true; 1010 } 1011 }break ; 1012case GGML_TYPE_IQ4_NL : 1013 { 1014nsg = N_SG_IQ4_NL ; 1015nr0 = N_R0_IQ4_NL ; 1016smem = 32 * sizeof (float ); 1017 }break ; 1018case GGML_TYPE_IQ4_XS : 1019 { 1020nsg = N_SG_IQ4_XS ; 1021nr0 = N_R0_IQ4_XS ; 1022smem = 32 * sizeof (float ); 1023 }break ; 1024case GGML_TYPE_TQ2_0 : 1025 { 1026nsg = N_SG_TQ2_0 ; 1027nr0 = N_R0_TQ2_0 ; 1028 }break ; 1029default : 1030 { 1031GGML_LOG_ERROR ("Asserting on type %d\n" , (int )tsrc0 ); 1032GGML_ABORT ("not implemented" ); 1033 } 1034 }; 1035 1036GGML_ASSERT (ne12 <=INT16_MAX && ne13 <=INT16_MAX ); 1037const int16_t r2 = (int16_t ) (ne12 /ne02 ); 1038const int16_t r3 = (int16_t ) (ne13 /ne03 ); 1039 1040snprintf (base ,256 ,"kernel_mul_mv_%s_%s%s" ,ggml_type_name (tsrc0 ),ggml_type_name (tsrc1 ),suffix ); 1041snprintf (name ,256 ,"%s_nsg=%d_ne12=%d_r2=%d_r3=%d_split=%d" ,base ,nsg ,ne12 ,r2 ,r3 ,split ); 1042 1043ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1044if (!res .pipeline ) { 1045ggml_metal_cv_t cv = ggml_metal_cv_init (); 1046 1047ggml_metal_cv_set_int16 (cv ,nsg ,FC_MUL_MV + 0 ); 1048ggml_metal_cv_set_int16 (cv , (int16_t )ne12 ,FC_MUL_MV + 2 ); 1049ggml_metal_cv_set_int16 (cv ,r2 ,FC_MUL_MV + 3 ); 1050ggml_metal_cv_set_int16 (cv ,r3 ,FC_MUL_MV + 4 ); 1051ggml_metal_cv_set_bool (cv ,split ,FC_MUL_MV + 5 ); 1052 1053res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1054 1055ggml_metal_cv_free (cv ); 1056 } 1057 1058res .nr0 = nr0 ; 1059res .nr1 = nr1 ; 1060res .nsg = nsg ; 1061res .smem = smem ; 1062 1063return res ; 1064} 1065 1066ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_mul_mm_id_map0 (ggml_metal_library_t lib ,int ne02 ,int ne20 ) { 1067char base [256 ]; 1068char name [256 ]; 1069 1070snprintf (base ,256 ,"kernel_mul_mm_id_map0_ne20_%d" ,ne20 ); 1071snprintf (name ,256 ,"%s_ne02=%d" ,base ,ne02 ); 1072 1073ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1074if (!res .pipeline ) { 1075res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1076 } 1077 1078res .smem = (size_t )ne02 * ne20 * sizeof (uint16_t ); 1079res .smem = GGML_PAD (res .smem ,16 ); 1080 1081return res ; 1082} 1083 1084ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_mul_mm_id (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1085char base [256 ]; 1086char name [256 ]; 1087 1088const ggml_type tsrc0 = op -> src [0 ]-> type ; 1089const ggml_type tsrc1 = op -> src [1 ]-> type ; 1090 1091const bool bc_inp = op -> src [0 ]-> ne [0 ] %32 != 0 ; 1092 1093snprintf (base ,256 ,"kernel_mul_mm_id_%s_%s" ,ggml_type_name (tsrc0 ),ggml_type_name (tsrc1 )); 1094snprintf (name ,256 ,"%s_bci=%d" ,base ,bc_inp ); 1095 1096ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1097if (!res .pipeline ) { 1098ggml_metal_cv_t cv = ggml_metal_cv_init (); 1099 1100ggml_metal_cv_set_bool (cv ,bc_inp ,FC_MUL_MM + 0 ); 1101 1102res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1103 1104ggml_metal_cv_free (cv ); 1105 } 1106 1107res .smem = 8192 ; 1108 1109return res ; 1110} 1111 1112ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_mul_mv_id (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1113GGML_TENSOR_LOCALS (int32_t ,ne0 ,op -> src [0 ],ne ); 1114GGML_TENSOR_LOCALS (int32_t ,ne1 ,op -> src [1 ],ne ); 1115 1116char base [256 ]; 1117char name [256 ]; 1118 1119int nsg = 0 ;// number of simdgroups 1120int nr0 = 0 ;// number of src0 rows per simdgroup 1121int nr1 = 1 ;// number of src1 rows per threadgroup 1122 1123size_t smem = 0 ;// shared memory 1124 1125const ggml_type tsrc0 = op -> src [0 ]-> type ; 1126const ggml_type tsrc1 = op -> src [1 ]-> type ; 1127 1128const char * suffix = "" ; 1129 1130bool split = false; 1131 1132// use custom matrix x vector kernel 1133switch (tsrc0 ) { 1134case GGML_TYPE_F32 : 1135case GGML_TYPE_F16 : 1136case GGML_TYPE_BF16 : 1137 { 1138nsg = std::min (4 , (ne00 + 127 ) /128 ); 1139nr0 = 2 ; 1140nr1 = 1 ; 1141smem = 32 * sizeof (float )* nr0 ; 1142suffix = ne00 %4 == 0 ?"_4" :"" ; 1143 }break ; 1144case GGML_TYPE_Q1_0 : 1145 { 1146nsg = N_SG_Q1_0 ; 1147nr0 = N_R0_Q1_0 ; 1148 }break ; 1149case GGML_TYPE_Q2_0 : 1150 { 1151nsg = N_SG_Q2_0 ; 1152nr0 = N_R0_Q2_0 ; 1153 }break ; 1154case GGML_TYPE_Q4_0 : 1155 { 1156nsg = N_SG_Q4_0 ; 1157nr0 = N_R0_Q4_0 ; 1158 }break ; 1159case GGML_TYPE_Q4_1 : 1160 { 1161nsg = N_SG_Q4_1 ; 1162nr0 = N_R0_Q4_1 ; 1163 }break ; 1164case GGML_TYPE_Q5_0 : 1165 { 1166nsg = N_SG_Q5_0 ; 1167nr0 = N_R0_Q5_0 ; 1168 }break ; 1169case GGML_TYPE_Q5_1 : 1170 { 1171nsg = N_SG_Q5_1 ; 1172nr0 = N_R0_Q5_1 ; 1173 }break ; 1174case GGML_TYPE_Q8_0 : 1175 { 1176nsg = N_SG_Q8_0 ; 1177nr0 = N_R0_Q8_0 ; 1178smem = 32 * sizeof (float )* N_R0_Q8_0 ; 1179 }break ; 1180case GGML_TYPE_MXFP4 : 1181 { 1182nsg = N_SG_MXFP4 ; 1183nr0 = N_R0_MXFP4 ; 1184smem = 32 * sizeof (float ); 1185 }break ; 1186case GGML_TYPE_Q2_K : 1187 { 1188nsg = N_SG_Q2_K ; 1189nr0 = N_R0_Q2_K ; 1190 }break ; 1191case GGML_TYPE_Q3_K : 1192 { 1193nsg = N_SG_Q3_K ; 1194nr0 = N_R0_Q3_K ; 1195 }break ; 1196case GGML_TYPE_Q4_K : 1197 { 1198nsg = N_SG_Q4_K ; 1199nr0 = N_R0_Q4_K ; 1200 }break ; 1201case GGML_TYPE_Q5_K : 1202 { 1203nsg = N_SG_Q5_K ; 1204nr0 = N_R0_Q5_K ; 1205 }break ; 1206case GGML_TYPE_Q6_K : 1207 { 1208nsg = N_SG_Q6_K ; 1209nr0 = N_R0_Q6_K ; 1210 }break ; 1211case GGML_TYPE_IQ2_XXS : 1212 { 1213nsg = N_SG_IQ2_XXS ; 1214nr0 = N_R0_IQ2_XXS ; 1215smem = 256 * 8 + 128 ; 1216 1217const int nb32 = ne00 /32 ; 1218if (nb32 < 32 && (32 %nb32 )== 0 ) { 1219nr0 = N_R0_IQ2_XXS_SPLIT ; 1220split = true; 1221 } 1222 }break ; 1223case GGML_TYPE_IQ2_XS : 1224 { 1225nsg = N_SG_IQ2_XS ; 1226nr0 = N_R0_IQ2_XS ; 1227smem = 512 * 8 + 128 ; 1228 1229const int nb32 = ne00 /32 ; 1230if (nb32 < 32 && (32 %nb32 )== 0 ) { 1231nr0 = N_R0_IQ2_XS_SPLIT ; 1232split = true; 1233 } 1234 }break ; 1235case GGML_TYPE_IQ3_XXS : 1236 { 1237nsg = N_SG_IQ3_XXS ; 1238nr0 = N_R0_IQ3_XXS ; 1239smem = 256 * 4 + 128 ; 1240 1241// split the rows across threads when there are fewer than 32 chunks per row 1242const int nb32 = ne00 /32 ; 1243if (nb32 < 32 && (32 %nb32 )== 0 ) { 1244nr0 = N_R0_IQ3_XXS_SPLIT ; 1245split = true; 1246 } 1247 }break ; 1248case GGML_TYPE_IQ3_S : 1249 { 1250nsg = N_SG_IQ3_S ; 1251nr0 = N_R0_IQ3_S ; 1252smem = 512 * 4 ; 1253 1254const int nb32 = ne00 /32 ; 1255if (nb32 < 32 && (32 %nb32 )== 0 ) { 1256nr0 = N_R0_IQ3_S_SPLIT ; 1257split = true; 1258 } 1259 }break ; 1260case GGML_TYPE_IQ2_S : 1261 { 1262nsg = N_SG_IQ2_S ; 1263nr0 = N_R0_IQ2_S ; 1264 1265const int nb32 = ne00 /32 ; 1266if (nb32 < 32 && (32 %nb32 )== 0 ) { 1267nr0 = N_R0_IQ2_S_SPLIT ; 1268split = true; 1269 } 1270 }break ; 1271case GGML_TYPE_IQ1_S : 1272 { 1273nsg = N_SG_IQ1_S ; 1274nr0 = N_R0_IQ1_S ; 1275 1276const int nb32 = ne00 /32 ; 1277if (nb32 < 32 && (32 %nb32 )== 0 ) { 1278nr0 = N_R0_IQ1_S_SPLIT ; 1279split = true; 1280 } 1281 }break ; 1282case GGML_TYPE_IQ1_M : 1283 { 1284nsg = N_SG_IQ1_M ; 1285nr0 = N_R0_IQ1_M ; 1286 1287const int nb32 = ne00 /32 ; 1288if (nb32 < 32 && (32 %nb32 )== 0 ) { 1289nr0 = N_R0_IQ1_M_SPLIT ; 1290split = true; 1291 } 1292 }break ; 1293case GGML_TYPE_IQ4_NL : 1294 { 1295nsg = N_SG_IQ4_NL ; 1296nr0 = N_R0_IQ4_NL ; 1297smem = 32 * sizeof (float ); 1298 }break ; 1299case GGML_TYPE_IQ4_XS : 1300 { 1301nsg = N_SG_IQ4_XS ; 1302nr0 = N_R0_IQ4_XS ; 1303smem = 32 * sizeof (float ); 1304 }break ; 1305case GGML_TYPE_TQ2_0 : 1306 { 1307nsg = N_SG_TQ2_0 ; 1308nr0 = N_R0_TQ2_0 ; 1309 }break ; 1310default : 1311 { 1312GGML_LOG_ERROR ("Asserting on type %d\n" , (int )op -> src [2 ]-> type ); 1313GGML_ABORT ("not implemented" ); 1314 } 1315 }; 1316 1317snprintf (base ,256 ,"kernel_mul_mv_id_%s_%s%s" ,ggml_type_name (tsrc0 ),ggml_type_name (tsrc1 ),suffix ); 1318snprintf (name ,256 ,"%s_nsg=%d_split=%d" ,base ,nsg ,split ); 1319 1320ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1321if (!res .pipeline ) { 1322ggml_metal_cv_t cv = ggml_metal_cv_init (); 1323 1324ggml_metal_cv_set_int16 (cv ,nsg ,FC_MUL_MV + 0 ); 1325ggml_metal_cv_set_int16 (cv ,1 ,FC_MUL_MV + 2 ); 1326ggml_metal_cv_set_int16 (cv ,1 ,FC_MUL_MV + 3 ); 1327ggml_metal_cv_set_int16 (cv ,1 ,FC_MUL_MV + 4 ); 1328ggml_metal_cv_set_bool (cv ,split ,FC_MUL_MV + 5 ); 1329 1330res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1331 1332ggml_metal_cv_free (cv ); 1333 } 1334 1335res .nr0 = nr0 ; 1336res .nr1 = nr1 ; 1337res .nsg = nsg ; 1338res .smem = smem ; 1339 1340return res ; 1341} 1342 1343ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_argmax (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1344GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 ); 1345GGML_ASSERT (ggml_is_contiguous_1 (op -> src [0 ])); 1346GGML_ASSERT (op -> src [0 ]-> nb [0 ]== ggml_type_size (op -> src [0 ]-> type )); 1347 1348char base [256 ]; 1349char name [256 ]; 1350 1351snprintf (base ,256 ,"kernel_argmax_%s" ,ggml_type_name (op -> src [0 ]-> type )); 1352snprintf (name ,256 ,"%s" ,base ); 1353 1354ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1355if (!res .pipeline ) { 1356res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1357 } 1358 1359res .smem = 32 * (sizeof (float )+ sizeof (int32_t )); 1360 1361return res ; 1362} 1363 1364ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_argsort (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1365assert (op -> op == GGML_OP_ARGSORT ); 1366 1367char base [256 ]; 1368char name [256 ]; 1369 1370ggml_sort_order order = (ggml_sort_order )op -> op_params [0 ]; 1371 1372const char * order_str = "undefined" ; 1373switch (order ) { 1374case GGML_SORT_ORDER_ASC :order_str = "asc" ;break ; 1375case GGML_SORT_ORDER_DESC :order_str = "desc" ;break ; 1376default :GGML_ABORT ("fatal error" ); 1377 }; 1378 1379snprintf (base ,256 ,"kernel_argsort_%s_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> type ),order_str ); 1380snprintf (name ,256 ,"%s" ,base ); 1381 1382ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1383if (!res .pipeline ) { 1384res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1385 } 1386 1387return res ; 1388} 1389 1390ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_argsort_merge (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1391assert (op -> op == GGML_OP_ARGSORT ); 1392 1393char base [256 ]; 1394char name [256 ]; 1395 1396ggml_sort_order order = (ggml_sort_order )op -> op_params [0 ]; 1397 1398const char * order_str = "undefined" ; 1399switch (order ) { 1400case GGML_SORT_ORDER_ASC :order_str = "asc" ;break ; 1401case GGML_SORT_ORDER_DESC :order_str = "desc" ;break ; 1402default :GGML_ABORT ("fatal error" ); 1403 }; 1404 1405snprintf (base ,256 ,"kernel_argsort_merge_%s_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> type ),order_str ); 1406snprintf (name ,256 ,"%s" ,base ); 1407 1408ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1409if (!res .pipeline ) { 1410res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1411 } 1412 1413return res ; 1414} 1415 1416ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_fwht (ggml_metal_library_t lib ,int n ) { 1417char base [256 ]; 1418char name [256 ]; 1419 1420snprintf (base ,256 ,"kernel_fwht_f32_%d" ,n ); 1421snprintf (name ,256 ,"%s" ,base ); 1422 1423ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1424if (!res .pipeline ) { 1425res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1426 } 1427 1428return res ; 1429} 1430 1431// note: reuse the argsort kernel for the bitonic top_k fallback 1432ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_top_k (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1433assert (op -> op == GGML_OP_TOP_K ); 1434 1435char base [256 ]; 1436char name [256 ]; 1437 1438// note: the top_k kernel is always descending order 1439ggml_sort_order order = GGML_SORT_ORDER_DESC ; 1440 1441const char * order_str = "undefined" ; 1442switch (order ) { 1443case GGML_SORT_ORDER_ASC :order_str = "asc" ;break ; 1444case GGML_SORT_ORDER_DESC :order_str = "desc" ;break ; 1445default :GGML_ABORT ("fatal error" ); 1446 }; 1447 1448snprintf (base ,256 ,"kernel_argsort_%s_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> type ),order_str ); 1449snprintf (name ,256 ,"%s" ,base ); 1450 1451ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1452if (!res .pipeline ) { 1453res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1454 } 1455 1456return res ; 1457} 1458 1459ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_top_k_radix (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1460assert (op -> op == GGML_OP_TOP_K ); 1461 1462char base [256 ]; 1463char name [256 ]; 1464 1465snprintf (base ,256 ,"kernel_top_k_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> type )); 1466snprintf (name ,256 ,"%s" ,base ); 1467 1468ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1469if (!res .pipeline ) { 1470res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1471 } 1472 1473return res ; 1474} 1475 1476ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_top_k_merge (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1477assert (op -> op == GGML_OP_TOP_K ); 1478 1479char base [256 ]; 1480char name [256 ]; 1481 1482ggml_sort_order order = GGML_SORT_ORDER_DESC ; 1483 1484const char * order_str = "undefined" ; 1485switch (order ) { 1486case GGML_SORT_ORDER_ASC :order_str = "asc" ;break ; 1487case GGML_SORT_ORDER_DESC :order_str = "desc" ;break ; 1488default :GGML_ABORT ("fatal error" ); 1489 }; 1490 1491snprintf (base ,256 ,"kernel_argsort_merge_%s_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> type ),order_str ); 1492snprintf (name ,256 ,"%s" ,base ); 1493 1494ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1495if (!res .pipeline ) { 1496res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1497 } 1498 1499return res ; 1500} 1501 1502ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_flash_attn_ext_pad ( 1503ggml_metal_library_t lib , 1504const struct ggml_tensor * op , 1505bool has_mask , 1506int32_t ncpsg ) { 1507assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 1508GGML_UNUSED (op ); 1509 1510char base [256 ]; 1511char name [256 ]; 1512 1513snprintf (base ,256 ,"kernel_%s" , 1514"flash_attn_ext_pad" ); 1515 1516snprintf (name ,256 ,"%s_mask=%d_ncpsg=%d" , 1517base , 1518has_mask , 1519ncpsg ); 1520 1521ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1522if (!res .pipeline ) { 1523ggml_metal_cv_t cv = ggml_metal_cv_init (); 1524 1525ggml_metal_cv_set_bool (cv ,has_mask ,FC_FLASH_ATTN_EXT_PAD + 0 ); 1526//ggml_metal_cv_set_bool(cv, has_sinks, FC_FLASH_ATTN_EXT_PAD + 1); 1527//ggml_metal_cv_set_bool(cv, has_bias, FC_FLASH_ATTN_EXT_PAD + 2); 1528//ggml_metal_cv_set_bool(cv, has_scap, FC_FLASH_ATTN_EXT_PAD + 3); 1529 1530//ggml_metal_cv_set_int32(cv, ns10, FC_FLASH_ATTN_EXT_PAD + 20); 1531//ggml_metal_cv_set_int32(cv, ns20, FC_FLASH_ATTN_EXT_PAD + 21); 1532//ggml_metal_cv_set_int32(cv, nsg, FC_FLASH_ATTN_EXT_PAD + 22); 1533//ggml_metal_cv_set_int32(cv, nwg, FC_FLASH_ATTN_EXT_PAD + 23); 1534//ggml_metal_cv_set_int32(cv, nqptg, FC_FLASH_ATTN_EXT_PAD + 24); 1535ggml_metal_cv_set_int32 (cv ,ncpsg ,FC_FLASH_ATTN_EXT_PAD + 25 ); 1536 1537res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1538 1539ggml_metal_cv_free (cv ); 1540 } 1541 1542return res ; 1543} 1544 1545ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_flash_attn_ext_kv_f16 ( 1546ggml_metal_library_t lib , 1547const ggml_tensor * op ) { 1548assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 1549 1550char base [256 ]; 1551 1552snprintf (base ,256 ,"kernel_flash_attn_ext_kv_%s_f16" ,ggml_type_name (op -> src [1 ]-> type )); 1553 1554ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,base ); 1555if (!res .pipeline ) { 1556res = ggml_metal_library_compile_pipeline (lib ,base ,base ,nullptr ); 1557 } 1558 1559return res ; 1560} 1561 1562ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_flash_attn_ext_blk ( 1563ggml_metal_library_t lib , 1564const struct ggml_tensor * op , 1565int32_t nqptg , 1566int32_t ncpsg ) { 1567assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 1568GGML_UNUSED (op ); 1569 1570char base [256 ]; 1571char name [256 ]; 1572 1573snprintf (base ,256 ,"kernel_%s" , 1574"flash_attn_ext_blk" ); 1575 1576snprintf (name ,256 ,"%s_nqptg=%d_ncpsg=%d" , 1577base , 1578nqptg , 1579ncpsg ); 1580 1581ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1582if (!res .pipeline ) { 1583ggml_metal_cv_t cv = ggml_metal_cv_init (); 1584 1585//ggml_metal_cv_set_bool(cv, has_mask, FC_FLASH_ATTN_EXT_BLK + 0); 1586//ggml_metal_cv_set_bool(cv, has_sinks, FC_FLASH_ATTN_EXT_BLK + 1); 1587//ggml_metal_cv_set_bool(cv, has_bias, FC_FLASH_ATTN_EXT_BLK + 2); 1588//ggml_metal_cv_set_bool(cv, has_scap, FC_FLASH_ATTN_EXT_BLK + 3); 1589 1590//ggml_metal_cv_set_int32(cv, ns10, FC_FLASH_ATTN_EXT_BLK + 20); 1591//ggml_metal_cv_set_int32(cv, ns20, FC_FLASH_ATTN_EXT_BLK + 21); 1592//ggml_metal_cv_set_int32(cv, nsg, FC_FLASH_ATTN_EXT_BLK + 22); 1593//ggml_metal_cv_set_int32(cv, nwg, FC_FLASH_ATTN_EXT_BLK + 23); 1594ggml_metal_cv_set_int32 (cv ,nqptg ,FC_FLASH_ATTN_EXT_BLK + 24 ); 1595ggml_metal_cv_set_int32 (cv ,ncpsg ,FC_FLASH_ATTN_EXT_BLK + 25 ); 1596 1597res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1598 1599ggml_metal_cv_free (cv ); 1600 } 1601 1602return res ; 1603} 1604 1605ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_flash_attn_ext ( 1606ggml_metal_library_t lib , 1607const ggml_tensor * op , 1608bool has_mask , 1609bool has_sinks , 1610bool has_bias , 1611bool has_scap , 1612bool has_kvpad , 1613int32_t nsg , 1614bool use_kv_f16 , 1615int32_t ns10 , 1616int32_t ns20 ) { 1617assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 1618 1619char base [256 ]; 1620char name [256 ]; 1621 1622const int32_t dk = (int32_t )op -> src [1 ]-> ne [0 ]; 1623const int32_t dv = (int32_t )op -> src [2 ]-> ne [0 ]; 1624 1625const char * type = use_kv_f16 ?"f16" :ggml_type_name (op -> src [1 ]-> type ); 1626 1627// do bounds checks for the mask? 1628const bool bc_mask = op -> src [3 ]&& (op -> src [3 ]-> ne [1 ] %8 != 0 ); 1629 1630snprintf (base ,256 ,"kernel_%s_%s_dk%d_dv%d" , 1631"flash_attn_ext" , 1632type , 1633dk , 1634dv ); 1635 1636snprintf (name ,256 ,"%s_mask=%d_sinks=%d_bias=%d_scap=%d_kvpad=%d_bcm=%d_ns10=%d_ns20=%d_nsg=%d" , 1637base , 1638has_mask , 1639has_sinks , 1640has_bias , 1641has_scap , 1642has_kvpad , 1643bc_mask , 1644ns10 , 1645ns20 , 1646nsg ); 1647 1648ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1649if (!res .pipeline ) { 1650ggml_metal_cv_t cv = ggml_metal_cv_init (); 1651 1652ggml_metal_cv_set_bool (cv ,has_mask ,FC_FLASH_ATTN_EXT + 0 ); 1653ggml_metal_cv_set_bool (cv ,has_sinks ,FC_FLASH_ATTN_EXT + 1 ); 1654ggml_metal_cv_set_bool (cv ,has_bias ,FC_FLASH_ATTN_EXT + 2 ); 1655ggml_metal_cv_set_bool (cv ,has_scap ,FC_FLASH_ATTN_EXT + 3 ); 1656ggml_metal_cv_set_bool (cv ,has_kvpad ,FC_FLASH_ATTN_EXT + 4 ); 1657 1658ggml_metal_cv_set_bool (cv ,bc_mask ,FC_FLASH_ATTN_EXT + 10 ); 1659 1660ggml_metal_cv_set_int32 (cv ,ns10 ,FC_FLASH_ATTN_EXT + 20 ); 1661ggml_metal_cv_set_int32 (cv ,ns20 ,FC_FLASH_ATTN_EXT + 21 ); 1662ggml_metal_cv_set_int32 (cv ,nsg ,FC_FLASH_ATTN_EXT + 22 ); 1663 1664res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1665 1666ggml_metal_cv_free (cv ); 1667 } 1668 1669return res ; 1670} 1671 1672ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_flash_attn_ext_vec_idx ( 1673ggml_metal_library_t lib , 1674const ggml_tensor * op ) { 1675assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 1676assert (op -> src [3 ]); 1677 1678char name [256 ]; 1679 1680snprintf (name ,256 ,"kernel_flash_attn_ext_vec_idx" ); 1681 1682ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1683if (!res .pipeline ) { 1684res = ggml_metal_library_compile_pipeline (lib ,name ,name ,nullptr ); 1685 } 1686 1687GGML_UNUSED (op ); 1688 1689return res ; 1690} 1691 1692ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_flash_attn_ext_vec ( 1693ggml_metal_library_t lib , 1694const ggml_tensor * op , 1695bool has_mask , 1696bool has_sinks , 1697bool has_bias , 1698bool has_scap , 1699bool has_kvpad , 1700bool has_sparse , 1701int32_t nqpsg , 1702int32_t ne , 1703int32_t nsg , 1704int32_t nwg , 1705bool use_kv_f16 , 1706int32_t ns10 , 1707int32_t ns20 ) { 1708assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 1709 1710char base [256 ]; 1711char name [256 ]; 1712 1713const int32_t dk = (int32_t )op -> src [1 ]-> ne [0 ]; 1714const int32_t dv = (int32_t )op -> src [2 ]-> ne [0 ]; 1715 1716const char * type = use_kv_f16 ?"f16" :ggml_type_name (op -> src [1 ]-> type ); 1717 1718char qne_suffix [16 ]= {0 }; 1719if (!(nqpsg == 1 && ne == ggml_metal_tuning::fa_vec_baseline_ne (dk ,dv ))) { 1720snprintf (qne_suffix ,sizeof (qne_suffix ),"_q%d_ne%d" ,nqpsg ,ne ); 1721 } 1722 1723snprintf (base ,256 ,"kernel_%s_%s_dk%d_dv%d%s" , 1724"flash_attn_ext_vec" , 1725type , 1726dk , 1727dv , 1728qne_suffix ); 1729 1730snprintf (name ,256 ,"%s_mask=%d_sink=%d_bias=%d_scap=%d_kvpad=%d_sparse=%d_ns10=%d_ns20=%d_nsg=%d_nwg=%d" , 1731base , 1732has_mask , 1733has_sinks , 1734has_bias , 1735has_scap , 1736has_kvpad , 1737has_sparse , 1738ns10 , 1739ns20 , 1740nsg ,nwg ); 1741 1742ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1743if (!res .pipeline ) { 1744ggml_metal_cv_t cv = ggml_metal_cv_init (); 1745 1746ggml_metal_cv_set_bool (cv ,has_mask ,FC_FLASH_ATTN_EXT_VEC + 0 ); 1747ggml_metal_cv_set_bool (cv ,has_sinks ,FC_FLASH_ATTN_EXT_VEC + 1 ); 1748ggml_metal_cv_set_bool (cv ,has_bias ,FC_FLASH_ATTN_EXT_VEC + 2 ); 1749ggml_metal_cv_set_bool (cv ,has_scap ,FC_FLASH_ATTN_EXT_VEC + 3 ); 1750ggml_metal_cv_set_bool (cv ,has_kvpad ,FC_FLASH_ATTN_EXT_VEC + 4 ); 1751ggml_metal_cv_set_bool (cv ,has_sparse ,FC_FLASH_ATTN_EXT_VEC + 5 ); 1752 1753ggml_metal_cv_set_int32 (cv ,ns10 ,FC_FLASH_ATTN_EXT_VEC + 20 ); 1754ggml_metal_cv_set_int32 (cv ,ns20 ,FC_FLASH_ATTN_EXT_VEC + 21 ); 1755ggml_metal_cv_set_int32 (cv ,nsg ,FC_FLASH_ATTN_EXT_VEC + 22 ); 1756ggml_metal_cv_set_int32 (cv ,nwg ,FC_FLASH_ATTN_EXT_VEC + 23 ); 1757 1758res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1759 1760ggml_metal_cv_free (cv ); 1761 } 1762 1763return res ; 1764} 1765 1766ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_flash_attn_ext_vec_reduce ( 1767ggml_metal_library_t lib , 1768const ggml_tensor * op , 1769int32_t dv , 1770int32_t nwg ) { 1771assert (op -> op == GGML_OP_FLASH_ATTN_EXT ); 1772 1773char base [256 ]; 1774char name [256 ]; 1775 1776snprintf (base ,256 ,"kernel_flash_attn_ext_vec_reduce" ); 1777snprintf (name ,256 ,"%s_dv=%d_nwg=%d" ,base ,dv ,nwg ); 1778 1779ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1780if (!res .pipeline ) { 1781ggml_metal_cv_t cv = ggml_metal_cv_init (); 1782 1783ggml_metal_cv_set_int32 (cv ,dv ,FC_FLASH_ATTN_EXT_VEC_REDUCE + 0 ); 1784ggml_metal_cv_set_int32 (cv ,nwg ,FC_FLASH_ATTN_EXT_VEC_REDUCE + 1 ); 1785 1786res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1787 1788ggml_metal_cv_free (cv ); 1789 } 1790 1791return res ; 1792 1793GGML_UNUSED (op ); 1794} 1795 1796ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_bin (ggml_metal_library_t lib ,const ggml_tensor * op ,int32_t n_fuse ) { 1797char base [256 ]; 1798char name [256 ]; 1799 1800int op_num = -1 ; 1801 1802switch (op -> op ) { 1803case GGML_OP_ADD :op_num = 0 ;break ; 1804case GGML_OP_SUB :op_num = 1 ;break ; 1805case GGML_OP_MUL :op_num = 2 ;break ; 1806case GGML_OP_DIV :op_num = 3 ;break ; 1807default :GGML_ABORT ("fatal error" ); 1808 }; 1809 1810const char * t0_str = ggml_type_name (op -> src [0 ]-> type ); 1811const char * t1_str = ggml_type_name (op -> src [1 ]-> type ); 1812const char * t_str = ggml_type_name (op -> type ); 1813 1814const bool is_c4 = (op -> src [0 ]-> ne [0 ] %4 == 0 )&& (op -> src [1 ]-> ne [0 ] %4 == 0 ); 1815 1816const bool is_cb = op -> src [0 ]-> ne [0 ]!= op -> src [1 ]-> ne [0 ]; 1817const bool is_rb = ggml_is_contiguous (op -> src [0 ])&& ggml_is_contiguous (op -> src [1 ])&& (ggml_nrows (op -> src [1 ])== 1 )&& ggml_nelements (op )< 65536 ; 1818 1819snprintf (base ,256 ,"kernel_bin_fuse_%s_%s_%s%s" ,t0_str ,t1_str ,t_str ,is_c4 ?"_4" :"" ); 1820snprintf (name ,256 ,"%s_op=%d_nf=%d_rb=%d_cb=%d" ,base ,op_num ,n_fuse ,is_rb ,is_cb ); 1821 1822ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1823if (!res .pipeline ) { 1824ggml_metal_cv_t cv = ggml_metal_cv_init (); 1825 1826ggml_metal_cv_set_int16 (cv ,op_num ,FC_BIN + 0 ); 1827ggml_metal_cv_set_int16 (cv ,n_fuse ,FC_BIN + 1 ); 1828ggml_metal_cv_set_bool (cv ,is_rb ,FC_BIN + 2 ); 1829ggml_metal_cv_set_bool (cv ,is_cb ,FC_BIN + 3 ); 1830 1831res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1832 1833ggml_metal_cv_free (cv ); 1834 } 1835 1836res .c4 = is_c4 ; 1837res .cnt = is_rb ; 1838 1839return res ; 1840} 1841 1842ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_bin_one (ggml_metal_library_t lib ,ggml_op op ) { 1843char base [256 ]; 1844char name [256 ]; 1845 1846int op_num = -1 ; 1847 1848switch (op ) { 1849case GGML_OP_ADD :op_num = 0 ;break ; 1850case GGML_OP_SUB :op_num = 1 ;break ; 1851case GGML_OP_MUL :op_num = 2 ;break ; 1852case GGML_OP_DIV :op_num = 3 ;break ; 1853default :GGML_ABORT ("fatal error" ); 1854 }; 1855 1856snprintf (base ,256 ,"kernel_bin_fuse_%s_%s_%s" ,"f32" ,"f32" ,"f32" ); 1857snprintf (name ,256 ,"%s_op=%d_nf=%d" ,base ,op_num ,1 ); 1858 1859ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1860if (!res .pipeline ) { 1861ggml_metal_cv_t cv = ggml_metal_cv_init (); 1862 1863ggml_metal_cv_set_int16 (cv ,op_num ,FC_BIN + 0 ); 1864ggml_metal_cv_set_int16 (cv ,1 ,FC_BIN + 1 ); 1865ggml_metal_cv_set_bool (cv , false,FC_BIN + 2 ); 1866 1867res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 1868 1869ggml_metal_cv_free (cv ); 1870 } 1871 1872return res ; 1873} 1874 1875ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_l2_norm (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1876assert (op -> op == GGML_OP_L2_NORM ); 1877 1878char base [256 ]; 1879char name [256 ]; 1880 1881const bool is_c4 = op -> src [0 ]-> ne [0 ] %4 == 0 ; 1882 1883const char * t0_str = ggml_type_name (op -> src [0 ]-> type ); 1884const char * t_str = ggml_type_name (op -> type ); 1885 1886snprintf (base ,256 ,"kernel_l2_norm_%s_%s%s" ,t0_str ,t_str ,is_c4 ?"_4" :"" ); 1887snprintf (name ,256 ,"%s" ,base ); 1888 1889ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1890if (!res .pipeline ) { 1891res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1892 } 1893 1894res .c4 = is_c4 ; 1895res .smem = 32 * sizeof (float ); 1896 1897return res ; 1898} 1899 1900ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_group_norm (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1901assert (op -> op == GGML_OP_GROUP_NORM ); 1902 1903GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 1904 1905char base [256 ]; 1906char name [256 ]; 1907 1908snprintf (base ,256 ,"kernel_group_norm_f32" ); 1909snprintf (name ,256 ,"%s" ,base ); 1910 1911ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1912if (!res .pipeline ) { 1913res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1914 } 1915 1916res .smem = 32 * sizeof (float ); 1917 1918return res ; 1919} 1920 1921ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_norm (ggml_metal_library_t lib ,const ggml_tensor * op ,int n_fuse ) { 1922assert (op -> op == GGML_OP_NORM || op -> op == GGML_OP_RMS_NORM ); 1923 1924GGML_ASSERT (ggml_is_contiguous_rows (op -> src [0 ])); 1925 1926char base [256 ]; 1927char name [256 ]; 1928 1929const char * suffix = "" ; 1930if (op -> ne [0 ] %4 == 0 ) { 1931suffix = "_4" ; 1932 } 1933 1934switch (op -> op ) { 1935case GGML_OP_NORM : 1936switch (n_fuse ) { 1937case 1 :snprintf (base ,256 ,"kernel_norm_f32%s" ,suffix );break ; 1938case 2 :snprintf (base ,256 ,"kernel_norm_mul_f32%s" ,suffix );break ; 1939case 3 :snprintf (base ,256 ,"kernel_norm_mul_add_f32%s" ,suffix );break ; 1940default :GGML_ABORT ("fatal error" ); 1941 }break ; 1942case GGML_OP_RMS_NORM : 1943switch (n_fuse ) { 1944case 1 :snprintf (base ,256 ,"kernel_rms_norm_f32%s" ,suffix );break ; 1945case 2 :snprintf (base ,256 ,"kernel_rms_norm_mul_f32%s" ,suffix );break ; 1946case 3 :snprintf (base ,256 ,"kernel_rms_norm_mul_add_f32%s" ,suffix );break ; 1947default :GGML_ABORT ("fatal error" ); 1948 }break ; 1949default :GGML_ABORT ("fatal error" ); 1950 } 1951 1952snprintf (name ,256 ,"%s" ,base ); 1953 1954ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1955if (!res .pipeline ) { 1956res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 1957 } 1958 1959res .smem = 32 * sizeof (float ); 1960 1961return res ; 1962} 1963 1964ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_rope (ggml_metal_library_t lib ,const ggml_tensor * op ) { 1965assert (op -> op == GGML_OP_ROPE || op -> op == GGML_OP_ROPE_BACK ); 1966 1967const bool is_back = op -> op == GGML_OP_ROPE_BACK ; 1968 1969char base [256 ]; 1970char name [256 ]; 1971 1972const int mode = ((const int32_t * )op -> op_params )[2 ]; 1973 1974const bool is_neox = mode & GGML_ROPE_TYPE_NEOX ; 1975const bool is_mrope = mode & GGML_ROPE_TYPE_MROPE ; 1976const bool is_imrope = mode == GGML_ROPE_TYPE_IMROPE ; 1977const bool is_vision = mode == GGML_ROPE_TYPE_VISION ; 1978 1979if (is_neox ) { 1980snprintf (base ,256 ,"kernel_rope_neox_%s" ,ggml_type_name (op -> src [0 ]-> type )); 1981 }else if ((is_mrope || is_imrope )&& !is_vision ) { 1982GGML_ASSERT (op -> src [1 ]-> ne [0 ]* 4 >=op -> src [0 ]-> ne [2 ]);// need at least 4 pos per token 1983snprintf (base ,256 ,"kernel_rope_multi_%s" ,ggml_type_name (op -> src [0 ]-> type )); 1984 }else if (is_vision ) { 1985GGML_ASSERT (op -> src [1 ]-> ne [0 ]* 4 >=op -> src [0 ]-> ne [2 ]);// need at least 4 pos per token 1986snprintf (base ,256 ,"kernel_rope_vision_%s" ,ggml_type_name (op -> src [0 ]-> type )); 1987 }else { 1988snprintf (base ,256 ,"kernel_rope_norm_%s" ,ggml_type_name (op -> src [0 ]-> type )); 1989 } 1990 1991snprintf (name ,256 ,"%s_imrope=%d_is_back=%d" ,base ,is_imrope ?1 :0 ,is_back ?1 :0 ); 1992 1993ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 1994if (!res .pipeline ) { 1995ggml_metal_cv_t cv = ggml_metal_cv_init (); 1996 1997ggml_metal_cv_set_bool (cv ,is_imrope ,FC_ROPE + 0 ); 1998ggml_metal_cv_set_bool (cv ,is_back ,FC_ROPE + 1 ); 1999 2000res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 2001 2002ggml_metal_cv_free (cv ); 2003 } 2004 2005return res ; 2006} 2007 2008ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_im2col (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2009assert (op -> op == GGML_OP_IM2COL ); 2010 2011GGML_TENSOR_LOCALS (int64_t ,ne0 ,op -> src [0 ],ne ); 2012 2013GGML_ASSERT (ggml_is_contiguous (op -> src [1 ])); 2014GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 2015GGML_ASSERT (op -> type == GGML_TYPE_F16 || op -> type == GGML_TYPE_F32 ); 2016 2017const bool is_2D = ((const int32_t * )(op -> op_params ))[6 ]== 1 ; 2018const int64_t KH = is_2D ?ne01 :1 ; 2019const int64_t KW = ne00 ; 2020 2021char base [256 ]; 2022char name [256 ]; 2023 2024if (KH * KW <=1024 ) { 2025snprintf (base ,256 ,"kernel_im2col_%s" ,ggml_type_name (op -> type )); 2026 }else { 2027snprintf (base ,256 ,"kernel_im2col_ext_%s" ,ggml_type_name (op -> type )); 2028 } 2029snprintf (name ,256 ,"%s" ,base ); 2030 2031ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2032if (!res .pipeline ) { 2033res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2034 } 2035 2036return res ; 2037} 2038 2039ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_conv_transpose_1d (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2040assert (op -> op == GGML_OP_CONV_TRANSPOSE_1D ); 2041 2042GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 2043GGML_ASSERT (ggml_is_contiguous (op -> src [1 ])); 2044GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_F32 ); 2045GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 2046GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 2047 2048char base [256 ]; 2049char name [256 ]; 2050 2051snprintf (base ,256 ,"kernel_conv_transpose_1d_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> src [1 ]-> type )); 2052snprintf (name ,256 ,"%s" ,base ); 2053 2054ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2055if (!res .pipeline ) { 2056res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2057 } 2058 2059return res ; 2060} 2061 2062ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_col2im_1d (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2063assert (op -> op == GGML_OP_COL2IM_1D ); 2064 2065GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 2066GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F32 || op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_BF16 ); 2067 2068char base [256 ]; 2069char name [256 ]; 2070 2071snprintf (base ,256 ,"kernel_col2im_1d_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2072snprintf (name ,256 ,"%s" ,base ); 2073 2074ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2075if (!res .pipeline ) { 2076res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2077 } 2078 2079return res ; 2080} 2081 2082ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_snake (ggml_metal_library_t lib ,enum ggml_type type ) { 2083GGML_ASSERT (type == GGML_TYPE_F32 || type == GGML_TYPE_F16 || type == GGML_TYPE_BF16 ); 2084 2085char base [256 ]; 2086char name [256 ]; 2087 2088snprintf (base ,256 ,"kernel_snake_%s" ,ggml_type_name (type )); 2089snprintf (name ,256 ,"%s" ,base ); 2090 2091ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2092if (!res .pipeline ) { 2093res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2094 } 2095 2096return res ; 2097} 2098 2099ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_conv_transpose_2d (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2100assert (op -> op == GGML_OP_CONV_TRANSPOSE_2D ); 2101 2102GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 2103GGML_ASSERT (ggml_is_contiguous (op -> src [1 ])); 2104GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_F32 ); 2105GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 2106GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 2107 2108char base [256 ]; 2109char name [256 ]; 2110 2111snprintf (base ,256 ,"kernel_conv_transpose_2d_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> src [1 ]-> type )); 2112snprintf (name ,256 ,"%s" ,base ); 2113 2114ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2115if (!res .pipeline ) { 2116res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2117 } 2118 2119return res ; 2120} 2121 2122ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_conv_2d (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2123assert (op -> op == GGML_OP_CONV_2D ); 2124 2125GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 2126GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_F32 ); 2127GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 2128GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 2129 2130char base [256 ]; 2131char name [256 ]; 2132 2133snprintf (base ,256 ,"kernel_conv_2d_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> src [1 ]-> type )); 2134snprintf (name ,256 ,"%s" ,base ); 2135 2136ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2137if (!res .pipeline ) { 2138res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2139 } 2140 2141return res ; 2142} 2143 2144ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_conv_2d_dw (ggml_metal_library_t lib ,const ggml_tensor * op ,bool tiled ) { 2145assert (op -> op == GGML_OP_CONV_2D_DW ); 2146 2147GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_F32 ); 2148GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 2149GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 2150 2151char base [256 ]; 2152char name [256 ]; 2153 2154snprintf (base ,256 ,"kernel_conv_2d_dw%s_%s_%s" , 2155tiled ?"_tiled" :"" , 2156ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> src [1 ]-> type )); 2157snprintf (name ,256 ,"%s" ,base ); 2158 2159ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2160if (!res .pipeline ) { 2161res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2162 } 2163 2164return res ; 2165} 2166 2167ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_conv_3d (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2168assert (op -> op == GGML_OP_CONV_3D ); 2169 2170GGML_ASSERT (ggml_is_contiguous (op -> src [0 ])); 2171GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_F16 || op -> src [0 ]-> type == GGML_TYPE_F32 ); 2172GGML_ASSERT (op -> src [1 ]-> type == GGML_TYPE_F32 ); 2173GGML_ASSERT (op -> type == GGML_TYPE_F32 ); 2174 2175char base [256 ]; 2176char name [256 ]; 2177 2178snprintf (base ,256 ,"kernel_conv_3d_%s_%s" ,ggml_type_name (op -> src [0 ]-> type ),ggml_type_name (op -> src [1 ]-> type )); 2179snprintf (name ,256 ,"%s" ,base ); 2180 2181ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2182if (!res .pipeline ) { 2183res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2184 } 2185 2186return res ; 2187} 2188 2189ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_upscale (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2190assert (op -> op == GGML_OP_UPSCALE ); 2191 2192char base [256 ]; 2193char name [256 ]; 2194 2195const int32_t mode_flags = ggml_get_op_params_i32 (op ,0 ); 2196const ggml_scale_mode mode = (ggml_scale_mode ) (mode_flags & 0xFF ); 2197 2198const bool antialias = (mode_flags & GGML_SCALE_FLAG_ANTIALIAS ); 2199 2200if (mode == GGML_SCALE_MODE_BILINEAR ) { 2201snprintf (base ,256 ,"kernel_upscale_bilinear_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2202 }else if (mode == GGML_SCALE_MODE_BICUBIC ) { 2203snprintf (base ,256 ,"kernel_upscale_bicubic_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2204 }else { 2205snprintf (base ,256 ,"kernel_upscale_nearest_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2206 } 2207snprintf (name ,256 ,"%s_aa=%d" ,base ,antialias ); 2208 2209ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2210if (!res .pipeline ) { 2211ggml_metal_cv_t cv = ggml_metal_cv_init (); 2212 2213ggml_metal_cv_set_bool (cv ,antialias ,FC_UPSCALE + 0 ); 2214 2215res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 2216 2217ggml_metal_cv_free (cv ); 2218 } 2219 2220return res ; 2221} 2222 2223ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_roll (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2224assert (op -> op == GGML_OP_ROLL ); 2225 2226char base [256 ]; 2227char name [256 ]; 2228 2229snprintf (base ,256 ,"kernel_roll_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2230snprintf (name ,256 ,"%s" ,base ); 2231 2232ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2233if (!res .pipeline ) { 2234res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2235 } 2236 2237return res ; 2238} 2239 2240ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_pad (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2241assert (op -> op == GGML_OP_PAD ); 2242 2243char base [256 ]; 2244char name [256 ]; 2245 2246// note: this is slower 2247//const bool is_c4 = op->src[0]->ne[0] % 4 == 0 && op->ne[0] % 4 == 0; 2248const bool is_c4 = false; 2249 2250snprintf (base ,256 ,"kernel_pad_%s%s" ,ggml_type_name (op -> src [0 ]-> type ),is_c4 ?"_4" :"" ); 2251snprintf (name ,256 ,"%s" ,base ); 2252 2253ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2254if (res .pipeline ) { 2255return res ; 2256 } 2257 2258res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2259 2260res .c4 = is_c4 ; 2261 2262return res ; 2263} 2264 2265ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_pad_reflect_1d (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2266assert (op -> op == GGML_OP_PAD_REFLECT_1D ); 2267 2268char base [256 ]; 2269char name [256 ]; 2270 2271snprintf (base ,256 ,"kernel_pad_reflect_1d_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2272snprintf (name ,256 ,"%s" ,base ); 2273 2274ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2275if (!res .pipeline ) { 2276res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2277 } 2278 2279return res ; 2280} 2281 2282ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_arange (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2283assert (op -> op == GGML_OP_ARANGE ); 2284 2285char base [256 ]; 2286char name [256 ]; 2287 2288snprintf (base ,256 ,"kernel_arange_%s" ,ggml_type_name (op -> type )); 2289snprintf (name ,256 ,"%s" ,base ); 2290 2291ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2292if (!res .pipeline ) { 2293res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2294 } 2295 2296return res ; 2297} 2298 2299ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_timestep_embedding (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2300assert (op -> op == GGML_OP_TIMESTEP_EMBEDDING ); 2301 2302char base [256 ]; 2303char name [256 ]; 2304 2305snprintf (base ,256 ,"kernel_timestep_embedding_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2306snprintf (name ,256 ,"%s" ,base ); 2307 2308ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2309if (!res .pipeline ) { 2310res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2311 } 2312 2313return res ; 2314} 2315 2316ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_opt_step_adamw (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2317assert (op -> op == GGML_OP_OPT_STEP_ADAMW ); 2318 2319char base [256 ]; 2320char name [256 ]; 2321 2322snprintf (base ,256 ,"kernel_opt_step_adamw_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2323snprintf (name ,256 ,"%s" ,base ); 2324 2325ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2326if (!res .pipeline ) { 2327res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2328 } 2329 2330return res ; 2331} 2332 2333ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_opt_step_sgd (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2334assert (op -> op == GGML_OP_OPT_STEP_SGD ); 2335 2336char base [256 ]; 2337char name [256 ]; 2338 2339snprintf (base ,256 ,"kernel_opt_step_sgd_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2340snprintf (name ,256 ,"%s" ,base ); 2341 2342ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2343if (!res .pipeline ) { 2344res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2345 } 2346 2347return res ; 2348} 2349 2350ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_silu_back (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2351assert (op -> op == GGML_OP_SILU_BACK ); 2352 2353char base [256 ]; 2354char name [256 ]; 2355 2356snprintf (base ,256 ,"kernel_silu_back_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2357snprintf (name ,256 ,"%s" ,base ); 2358 2359ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2360if (!res .pipeline ) { 2361res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2362 } 2363 2364return res ; 2365} 2366 2367ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_memset (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2368GGML_ASSERT (op -> type == GGML_TYPE_I64 ); 2369 2370char base [256 ]; 2371char name [256 ]; 2372 2373snprintf (base ,256 ,"kernel_memset_%s" ,ggml_type_name (op -> type )); 2374snprintf (name ,256 ,"%s" ,base ); 2375 2376ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2377if (!res .pipeline ) { 2378res = ggml_metal_library_compile_pipeline (lib ,base ,name ,nullptr ); 2379 } 2380 2381return res ; 2382} 2383 2384ggml_metal_pipeline_with_params ggml_metal_library_get_pipeline_count_equal (ggml_metal_library_t lib ,const ggml_tensor * op ) { 2385assert (op -> op == GGML_OP_COUNT_EQUAL ); 2386 2387GGML_TENSOR_LOCALS (int64_t ,ne0 ,op -> src [0 ],ne ); 2388 2389GGML_ASSERT (op -> src [0 ]-> type == op -> src [1 ]-> type ); 2390GGML_ASSERT (op -> src [0 ]-> type == GGML_TYPE_I32 ); 2391GGML_ASSERT (op -> type == GGML_TYPE_I64 ); 2392 2393// note: the kernel only supports i32 output due to metal atomic add only supporting atomic_int 2394GGML_ASSERT (ggml_nelements (op -> src [0 ])< (1LL <<31 )); 2395 2396char base [256 ]; 2397char name [256 ]; 2398 2399int nsg = 1 ; 2400while (32 * nsg < ne00 && nsg < 32 ) { 2401nsg *=2 ; 2402 } 2403 2404snprintf (base ,256 ,"kernel_count_equal_%s" ,ggml_type_name (op -> src [0 ]-> type )); 2405snprintf (name ,256 ,"%s_nsg=%d" ,base ,nsg ); 2406 2407ggml_metal_pipeline_with_params res = ggml_metal_library_get_pipeline (lib ,name ); 2408if (!res .pipeline ) { 2409ggml_metal_cv_t cv = ggml_metal_cv_init (); 2410 2411ggml_metal_cv_set_int16 (cv ,nsg ,FC_COUNT_EQUAL + 0 ); 2412 2413res = ggml_metal_library_compile_pipeline (lib ,base ,name ,cv ); 2414 2415ggml_metal_cv_free (cv ); 2416 } 2417 2418res .smem = 32 * sizeof (int32_t ); 2419res .nsg = nsg ; 2420 2421return res ; 2422}