char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
0190529ec
char/aliceai-t5-moe
1#include "ggml-et-ops.h" 2 3#include "ggml-et-cpu-compare.h" 4#include "ggml-et-kernels.h" 5#include "ggml-impl.h" 6 7#include <stdio.h> 8 9#include <cstdint> 10 11// CPU comparison configuration - can be enabled for debugging 12static ggml_et_cpu_compare_config rope_cpu_compare_config = { 13/* .enabled = */ false, 14/* .use_cpu_result = */ false,// Replace ET result with CPU result 15/* .log_differences = */ true, 16/* .tolerance = */ 1e-5f , 17/* .max_log_elements = */ 4096 18}; 19 20static ggml_et_cpu_compare_config rms_norm_cpu_compare_config = { 21/* .enabled = */ false, 22/* .use_cpu_result = */ false, 23/* .log_differences = */ true, 24/* .tolerance = */ 1e-5f , 25/* .max_log_elements = */ 4096 26}; 27 28static ggml_et_cpu_compare_config norm_cpu_compare_config = { 29/* .enabled = */ false, 30/* .use_cpu_result = */ false, 31/* .log_differences = */ true, 32/* .tolerance = */ 1e-5f , 33/* .max_log_elements = */ 4096 34}; 35 36static ggml_et_cpu_compare_config l2_norm_cpu_compare_config = { 37/* .enabled = */ false, 38/* .use_cpu_result = */ false, 39/* .log_differences = */ true, 40/* .tolerance = */ 1e-5f , 41/* .max_log_elements = */ 4096 42}; 43 44static ggml_et_cpu_compare_config group_norm_cpu_compare_config = { 45/* .enabled = */ false, 46/* .use_cpu_result = */ false, 47/* .log_differences = */ true, 48/* .tolerance = */ 1e-5f , 49/* .max_log_elements = */ 4096 50}; 51 52static ggml_et_cpu_compare_config im2col_cpu_compare_config = { 53/* .enabled = */ false, 54/* .use_cpu_result = */ false, 55/* .log_differences = */ true, 56/* .tolerance = */ 1e-5f , 57/* .max_log_elements = */ 4096 58}; 59 60static ggml_et_cpu_compare_config unary_cpu_compare_config = { 61/* .enabled = */ false, 62/* .use_cpu_result = */ false, 63/* .log_differences = */ true, 64/* .tolerance = */ 1e-4f , 65/* .max_log_elements = */ 4096 66}; 67 68static ggml_et_cpu_compare_config sum_rows_cpu_compare_config = { 69/* .enabled = */ false, 70/* .use_cpu_result = */ false, 71/* .log_differences = */ true, 72/* .tolerance = */ 1e-5f , 73/* .max_log_elements = */ 4096 74}; 75 76static ggml_et_cpu_compare_config clamp_cpu_compare_config = { 77/* .enabled = */ false, 78/* .use_cpu_result = */ false, 79/* .log_differences = */ true, 80/* .tolerance = */ 1e-6f , 81/* .max_log_elements = */ 4096 82}; 83 84static ggml_et_cpu_compare_config mean_cpu_compare_config = { 85/* .enabled = */ false, 86/* .use_cpu_result = */ false, 87/* .log_differences = */ true, 88/* .tolerance = */ 1e-5f , 89/* .max_log_elements = */ 4096 90}; 91 92static ggml_et_cpu_compare_config sqr_cpu_compare_config = { 93/* .enabled = */ false, 94/* .use_cpu_result = */ false, 95/* .log_differences = */ true, 96/* .tolerance = */ 1e-6f , 97/* .max_log_elements = */ 4096 98}; 99 100static ggml_et_cpu_compare_config elmap_cpu_compare_config = { 101/* .enabled = */ false, 102/* .use_cpu_result = */ false, 103/* .log_differences = */ true, 104/* .tolerance = */ 1e-6f , 105/* .max_log_elements = */ 4096 106}; 107 108static ggml_et_cpu_compare_config glu_cpu_compare_config = { 109/* .enabled = */ false, 110/* .use_cpu_result = */ false, 111/* .log_differences = */ true, 112/* .tolerance = */ 1e-5f , 113/* .max_log_elements = */ 4096 114}; 115 116static ggml_et_cpu_compare_config mul_mat_cpu_compare_config = { 117/* .enabled = */ false, 118/* .use_cpu_result = */ false, 119/* .log_differences = */ true, 120/* .tolerance = */ 0.01 , 121/* .max_log_elements = */ 4096 122}; 123 124static ggml_et_cpu_compare_config mul_mat_id_cpu_compare_config = { 125/* .enabled = */ false, 126/* .use_cpu_result = */ false, 127/* .log_differences = */ true, 128/* .tolerance = */ 0.01 , 129/* .max_log_elements = */ 4096 130}; 131 132static ggml_et_cpu_compare_config softmax_cpu_compare_config = { 133/* .enabled = */ false, 134/* .use_cpu_result = */ false, 135/* .log_differences = */ true, 136/* .tolerance = */ 1e-5f , 137/* .max_log_elements = */ 1024 138}; 139 140static ggml_et_cpu_compare_config get_rows_cpu_compare_config = { 141/* .enabled = */ false, 142/* .use_cpu_result = */ false, 143/* .log_differences = */ true, 144/* .tolerance = */ 1e-6f , 145/* .max_log_elements = */ 2048 146}; 147 148static ggml_et_cpu_compare_config pad_cpu_compare_config = { 149/* .enabled = */ false, 150/* .use_cpu_result = */ false, 151/* .log_differences = */ true, 152/* .tolerance = */ 1e-6f , 153/* .max_log_elements = */ 4096 154}; 155 156static ggml_et_cpu_compare_config cont_cpu_compare_config = { 157/* .enabled = */ false, 158/* .use_cpu_result = */ false, 159/* .log_differences = */ true, 160/* .tolerance = */ 1e-6f , 161/* .max_log_elements = */ 4096 162}; 163 164static ggml_et_cpu_compare_config concat_cpu_compare_config = { 165/* .enabled = */ false, 166/* .use_cpu_result = */ false, 167/* .log_differences = */ true, 168/* .tolerance = */ 1e-6f , 169/* .max_log_elements = */ 4096 170}; 171 172static ggml_et_cpu_compare_config cumsum_cpu_compare_config = { 173/* .enabled = */ false, 174/* .use_cpu_result = */ false, 175/* .log_differences = */ true, 176/* .tolerance = */ 1e-6f , 177/* .max_log_elements = */ 4096 178}; 179 180static ggml_et_cpu_compare_config repeat_cpu_compare_config = { 181/* .enabled = */ false, 182/* .use_cpu_result = */ false, 183/* .log_differences = */ true, 184/* .tolerance = */ 1e-6f , 185/* .max_log_elements = */ 4096 186}; 187 188static ggml_et_cpu_compare_config ssm_conv_cpu_compare_config = { 189/* .enabled = */ false, 190/* .use_cpu_result = */ false, 191/* .log_differences = */ true, 192/* .tolerance = */ 1e-6f , 193/* .max_log_elements = */ 4096 194}; 195 196static ggml_et_cpu_compare_config rwkv_wkv6_cpu_compare_config = { 197/* .enabled = */ false, 198/* .use_cpu_result = */ false, 199/* .log_differences = */ true, 200/* .tolerance = */ 1e-4f , 201/* .max_log_elements = */ 4096 202}; 203 204static ggml_et_cpu_compare_config rwkv_wkv7_cpu_compare_config = { 205/* .enabled = */ false, 206/* .use_cpu_result = */ false, 207/* .log_differences = */ true, 208/* .tolerance = */ 1e-4f , 209/* .max_log_elements = */ 4096 210}; 211 212static ggml_et_cpu_compare_config set_rows_cpu_compare_config = { 213/* .enabled = */ false, 214/* .use_cpu_result = */ false, 215/* .log_differences = */ true, 216/* .tolerance = */ 1e-6f , 217/* .max_log_elements = */ 2048 218}; 219 220bool ggml_et_op_rms_norm_mul (ggml_backend_et_device_context * dev_ctx , 221const ggml_tensor * rms_norm_node , 222const ggml_tensor * mul_node ) { 223ET_PERF_START (); 224 225if (!dev_ctx || !rms_norm_node || !mul_node ) { 226GGML_LOG_ERROR ("ET: Invalid parameters for fused RMS_NORM_MUL operation\n" ); 227return false; 228 } 229 230if (!rms_norm_node -> src [0 ]) { 231GGML_LOG_ERROR ("ET: Fused RMS_NORM_MUL missing required input\n" ); 232return false; 233 } 234 235// Extract weights: the MUL operand that isn't the rms_norm output 236const ggml_tensor * weights = (mul_node -> src [0 ]== rms_norm_node ) ?mul_node -> src [1 ] :mul_node -> src [0 ]; 237 238if (!weights ) { 239GGML_LOG_ERROR ("ET: Fused RMS_NORM_MUL missing weights tensor\n" ); 240return false; 241 } 242 243float eps ; 244memcpy (& eps ,rms_norm_node -> op_params ,sizeof (float )); 245 246ggml_et_rms_norm_mul_params params ; 247params .src0 = * rms_norm_node -> src [0 ];// input to normalize 248params .src1 = * weights ;// normalization weights 249params .dst = * mul_node ;// final output 250params .eps = eps ; 251 252bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"rms_norm_mul_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 253 254ET_PERF_END_EXT ("RMS_NORM_MUL" ,"rms_norm_mul_f32" ,mul_node ,"eps=%.6f" , (double )eps ); 255return kernel_result ; 256} 257 258bool ggml_et_op_scale (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 259ET_PERF_START (); 260 261if (!dev_ctx || !node ) { 262GGML_LOG_ERROR ("ET: Invalid parameters for SCALE operation\n" ); 263return false; 264 } 265 266if (!node -> src [0 ]) { 267GGML_LOG_ERROR ("ET: SCALE operation missing required input\n" ); 268return false; 269 } 270 271if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 272GGML_LOG_ERROR ("ET: SCALE operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 273ggml_type_name (node -> src [0 ]-> type )); 274return false; 275 } 276 277float scale ,bias ; 278memcpy (& scale , (const float * )node -> op_params + 0 ,sizeof (float )); 279memcpy (& bias , (const float * )node -> op_params + 1 ,sizeof (float )); 280 281ggml_et_scale_params params ; 282params .src0 = * node -> src [0 ]; 283params .dst = * node ; 284params .scale = scale ; 285params .bias = bias ; 286 287bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"scale_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 288 289ET_PERF_END_EXT ("SCALE" ,"scale_f32" ,node ,"scale=%.6f|bias=%.6f" , (double )scale , (double )bias ); 290return kernel_result ; 291} 292 293bool ggml_et_op_sqr (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 294ET_PERF_START (); 295 296if (!dev_ctx || !node ) { 297GGML_LOG_ERROR ("ET: Invalid parameters for SQR operation\n" ); 298return false; 299 } 300 301if (!node -> src [0 ]) { 302GGML_LOG_ERROR ("ET: SQR operation missing required input\n" ); 303return false; 304 } 305 306if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 307GGML_LOG_ERROR ("ET: SQR operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 308ggml_type_name (node -> src [0 ]-> type )); 309return false; 310 } 311 312ggml_et_sqr_params params ; 313params .src0 = * node -> src [0 ];// F32 input tensor 314params .dst = * node ;// F32 output tensor 315 316// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 317ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 318bool cpu_comparison_active = false; 319if (sqr_cpu_compare_config .enabled ) { 320if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_SQR )) { 321cpu_comparison_active = true; 322 }else { 323GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for SQR operation\n" ); 324 } 325 } 326 327bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"sqr_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 328 329// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 330if (cpu_comparison_active ) { 331if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& sqr_cpu_compare_config )) { 332GGML_LOG_WARN ("ET: CPU comparison failed for SQR operation\n" ); 333 } 334ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 335 } 336 337ET_PERF_END ("SQR" ,"sqr_f32" ,node ); 338return kernel_result ; 339} 340 341bool ggml_et_op_sum_rows (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 342ET_PERF_START (); 343 344if (!dev_ctx || !node ) { 345GGML_LOG_ERROR ("ET: Invalid parameters for SUM_ROWS operation\n" ); 346return false; 347 } 348 349if (!node -> src [0 ]) { 350GGML_LOG_ERROR ("ET: SUM_ROWS operation missing required input\n" ); 351return false; 352 } 353 354if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 355GGML_LOG_ERROR ("ET: SUM_ROWS operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 356ggml_type_name (node -> src [0 ]-> type )); 357return false; 358 } 359 360ggml_et_sum_rows_params params ; 361params .src0 = * node -> src [0 ]; 362params .dst = * node ; 363 364// Phase 1: Initialize CPU comparison context 365ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 366bool cpu_comparison_active = false; 367if (sum_rows_cpu_compare_config .enabled ) { 368if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_SUM_ROWS )) { 369cpu_comparison_active = true; 370 }else { 371GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for SUM_ROWS operation\n" ); 372 } 373 } 374 375bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"sum_rows_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 376 377// Phase 2: Execute CPU computation and compare 378if (cpu_comparison_active ) { 379if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& sum_rows_cpu_compare_config )) { 380GGML_LOG_WARN ("ET: CPU comparison failed for SUM_ROWS operation\n" ); 381 } 382ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 383 } 384 385ET_PERF_END ("SUM_ROWS" ,"sum_rows_f32" ,node ); 386return kernel_result ; 387} 388 389bool ggml_et_op_mean (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 390ET_PERF_START (); 391 392if (!dev_ctx || !node ) { 393GGML_LOG_ERROR ("ET: Invalid parameters for MEAN operation\n" ); 394return false; 395 } 396 397if (!node -> src [0 ]) { 398GGML_LOG_ERROR ("ET: MEAN operation missing required input\n" ); 399return false; 400 } 401 402if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 403GGML_LOG_ERROR ("ET: MEAN operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 404ggml_type_name (node -> src [0 ]-> type )); 405return false; 406 } 407 408ggml_et_mean_params params ; 409params .src0 = * node -> src [0 ]; 410params .dst = * node ; 411 412ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 413bool cpu_comparison_active = false; 414if (mean_cpu_compare_config .enabled ) { 415if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_MEAN )) { 416cpu_comparison_active = true; 417 }else { 418GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for MEAN operation\n" ); 419 } 420 } 421 422bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"mean_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 423 424if (cpu_comparison_active ) { 425if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& mean_cpu_compare_config )) { 426GGML_LOG_WARN ("ET: CPU comparison failed for MEAN operation\n" ); 427 } 428ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 429 } 430 431ET_PERF_END ("MEAN" ,"mean_f32" ,node ); 432return kernel_result ; 433} 434 435bool ggml_et_op_clamp (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 436ET_PERF_START (); 437 438if (!dev_ctx || !node ) { 439GGML_LOG_ERROR ("ET: Invalid parameters for CLAMP operation\n" ); 440return false; 441 } 442 443if (!node -> src [0 ]) { 444GGML_LOG_ERROR ("ET: CLAMP operation missing required input\n" ); 445return false; 446 } 447 448if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 449GGML_LOG_ERROR ("ET: CLAMP operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 450ggml_type_name (node -> src [0 ]-> type )); 451return false; 452 } 453 454ggml_et_clamp_params params ; 455params .src0 = * node -> src [0 ]; 456params .dst = * node ; 457// op_params layout per ggml.c::ggml_clamp: { min, max } as floats 458memcpy (& params .min_val , (const float * )node -> op_params + 0 ,sizeof (float )); 459memcpy (& params .max_val , (const float * )node -> op_params + 1 ,sizeof (float )); 460 461ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 462bool cpu_comparison_active = false; 463if (clamp_cpu_compare_config .enabled ) { 464if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_CLAMP )) { 465cpu_comparison_active = true; 466 }else { 467GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for CLAMP operation\n" ); 468 } 469 } 470 471bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"clamp_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 472 473if (cpu_comparison_active ) { 474if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& clamp_cpu_compare_config )) { 475GGML_LOG_WARN ("ET: CPU comparison failed for CLAMP operation\n" ); 476 } 477ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 478 } 479 480ET_PERF_END ("CLAMP" ,"clamp_f32" ,node ); 481return kernel_result ; 482} 483 484bool ggml_et_op_unary (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 485ET_PERF_START (); 486 487if (!dev_ctx || !node ) { 488GGML_LOG_ERROR ("ET: Invalid parameters for UNARY operation\n" ); 489return false; 490 } 491 492if (!node -> src [0 ]) { 493GGML_LOG_ERROR ("ET: UNARY operation missing required input\n" ); 494return false; 495 } 496 497if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 498GGML_LOG_ERROR ("ET: UNARY operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 499ggml_type_name (node -> src [0 ]-> type )); 500return false; 501 } 502 503const ggml_unary_op uop = ggml_get_unary_op (node ); 504const char * op_name = ggml_unary_op_name (uop ); 505 506ggml_et_unary_params params ; 507params .src0 = * node -> src [0 ];// F32 input tensor 508params .dst = * node ;// F32 output tensor 509params .unary_op = (int32_t )uop ; 510 511// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 512ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 513bool cpu_comparison_active = false; 514if (unary_cpu_compare_config .enabled ) { 515if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_UNARY )) { 516cpu_comparison_active = true; 517 }else { 518GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for UNARY/%s operation\n" ,op_name ); 519 } 520 } 521 522bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"unary_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 523 524// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 525if (cpu_comparison_active ) { 526if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& unary_cpu_compare_config )) { 527GGML_LOG_WARN ("ET: CPU comparison failed for UNARY/%s operation\n" ,op_name ); 528 } 529ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 530 } 531 532ET_PERF_END_EXT ("UNARY" ,"unary_f32" ,node ,"op=%s" ,op_name ); 533return kernel_result ; 534} 535 536bool ggml_et_op_mul (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 537// Delegate to generic element map operation 538return ggml_et_op_elmap (dev_ctx ,node ); 539} 540 541bool ggml_et_op_add (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 542// Delegate to generic element map operation 543return ggml_et_op_elmap (dev_ctx ,node ); 544} 545 546bool ggml_et_op_sub (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 547// Delegate to generic element map operation 548return ggml_et_op_elmap (dev_ctx ,node ); 549} 550 551bool ggml_et_op_elmap (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 552ET_PERF_START (); 553 554if (!dev_ctx || !node ) { 555GGML_LOG_ERROR ("ET: Invalid parameters for element map operation\n" ); 556return false; 557 } 558 559if (!node -> src [0 ]|| !node -> src [1 ]) { 560GGML_LOG_ERROR ("ET: Element map operation missing required inputs\n" ); 561return false; 562 } 563 564if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 || node -> src [1 ]-> type != GGML_TYPE_F32 ) { 565GGML_LOG_ERROR ("ET: Element map operation with unsupported types: dst=%s src0=%s src1=%s\n" , 566ggml_type_name (node -> type ),ggml_type_name (node -> src [0 ]-> type ), 567ggml_type_name (node -> src [1 ]-> type )); 568return false; 569 } 570 571const char * op_name = ggml_op_name (node -> op ); 572 573ggml_et_elmap_params params ; 574params .src0 = * node -> src [0 ]; 575params .src1 = * node -> src [1 ]; 576params .dst = * node ;// F32 output tensor (op type stored in dst.op) 577 578// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 579ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 580bool cpu_comparison_active = false; 581if (elmap_cpu_compare_config .enabled ) { 582if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,node -> op )) { 583cpu_comparison_active = true; 584 }else { 585GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for %s operation\n" ,op_name ); 586 } 587 } 588 589// fprintf(stderr, "ET: el_map s0 [%ld, %ld, %ld, %ld] s1 [%ld, %ld, %ld, %ld]\n", 590// node->src[0]->ne[0], node->src[0]->ne[1], node->src[0]->ne[2], node->src[0]->ne[3], 591// node->src[1]->ne[0], node->src[1]->ne[1], node->src[1]->ne[2], node->src[1]->ne[3]); 592 593bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"el_map_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 594 595// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 596if (cpu_comparison_active ) { 597if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& elmap_cpu_compare_config )) { 598GGML_LOG_WARN ("ET: CPU comparison failed for %s operation\n" ,op_name ); 599 } 600ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 601 } 602 603ET_PERF_END (op_name ,"el_map_f32" ,node ); 604return kernel_result ; 605} 606 607bool ggml_et_op_glu (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 608ET_PERF_START (); 609 610// Validate inputs 611if (!dev_ctx || !node ) { 612GGML_LOG_ERROR ("ET: Invalid parameters for GLU operation\n" ); 613return false; 614 } 615 616if (!node -> src [0 ]) { 617GGML_LOG_ERROR ("ET: GLU operation missing required input\n" ); 618return false; 619 } 620 621const bool is_split_mode = node -> src [1 ]!= nullptr ; 622 623// Only support F32 (as validated by supports_op) 624if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 || 625 (is_split_mode && node -> src [1 ]-> type != GGML_TYPE_F32 )) { 626return false; 627 } 628 629// Extract GLU operation parameters from op_params 630int32_t glu_op_type = ggml_get_op_params_i32 (node ,0 );// GLU variant (REGLU, GEGLU, SWIGLU, etc.) 631int32_t swapped = ggml_get_op_params_i32 (node ,1 );// Whether gate/value are swapped 632 633// Supported variants 634switch (glu_op_type ) { 635case GGML_GLU_OP_REGLU : 636case GGML_GLU_OP_GEGLU : 637case GGML_GLU_OP_SWIGLU : 638case GGML_GLU_OP_SWIGLU_OAI : 639case GGML_GLU_OP_SWIGLU_CLAMP : 640case GGML_GLU_OP_GEGLU_ERF : 641case GGML_GLU_OP_GEGLU_QUICK : 642break ; 643default : 644GGML_LOG_ERROR ("ET: GLU operation with unsupported variant: %s\n" , 645ggml_glu_op_name ((ggml_glu_op )glu_op_type )); 646return false; 647 } 648 649// Get GLU operation name for logging 650const char * glu_op_name = ggml_glu_op_name ((ggml_glu_op )glu_op_type ); 651 652// Pack parameters. Single-tensor mode is encoded by zeroing src1. 653ggml_et_glu_params params = {}; 654params .src0 = * node -> src [0 ]; 655if (is_split_mode ) { 656params .src1 = * node -> src [1 ]; 657 } 658params .dst = * node ; 659params .glu_op_type = glu_op_type ; 660params .swapped = swapped ; 661params .alpha = 0.0f ; 662params .limit = 0.0f ; 663if (glu_op_type == GGML_GLU_OP_SWIGLU_OAI ) { 664params .alpha = ggml_get_op_params_f32 (node ,2 ); 665 } 666if (glu_op_type == GGML_GLU_OP_SWIGLU_OAI || glu_op_type == GGML_GLU_OP_SWIGLU_CLAMP ) { 667params .limit = ggml_get_op_params_f32 (node ,3 ); 668 } 669// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 670ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 671bool cpu_comparison_active = false; 672if (glu_cpu_compare_config .enabled ) { 673if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_GLU )) { 674cpu_comparison_active = true; 675 }else { 676GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for %s operation\n" ,glu_op_name ); 677 } 678 } 679 680// Launch ET kernel 681bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"glu_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 682 683// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 684if (cpu_comparison_active ) { 685if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& glu_cpu_compare_config )) { 686GGML_LOG_WARN ("ET: CPU comparison failed for %s operation\n" ,glu_op_name ); 687 } 688ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 689 } 690 691ET_PERF_END ("GLU" ,"glu_f32" ,node ); 692return kernel_result ; 693} 694 695bool ggml_et_op_mul_mat (ggml_backend_et_device_context * dev_ctx , 696const ggml_tensor * node , 697const ggml_tensor * add_node ) { 698ET_PERF_START (); 699 700if (!dev_ctx || !node ) { 701GGML_LOG_ERROR ("ET: Invalid parameters for MUL_MAT operation\n" ); 702return false; 703 } 704 705if (!node -> src [0 ]|| !node -> src [1 ]) { 706GGML_LOG_ERROR ("ET: MUL_MAT operation missing required inputs\n" ); 707return false; 708 } 709 710// Fused MM+ADD: when add_node is non-NULL the caller has already validated 711// (Q8_0 weights, F32 acts, exact-shape ADD with stride parity to dst) via 712// ggml_et_can_fuse({MUL_MAT, ADD}). The kernel writes dst = mm + bias and 713// the ADD's output replaces MM's as the actual dst. 714const ggml_tensor * fused_dst = add_node ?add_node :node ; 715const ggml_tensor * bias_tensor = nullptr ; 716if (add_node ) { 717bias_tensor = (add_node -> src [0 ]== node ) ?add_node -> src [1 ] :add_node -> src [0 ]; 718 } 719 720const char * kernel_name ; 721const char * src0_type_name ; 722 723if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_Q4_0 && node -> src [1 ]-> type == GGML_TYPE_F32 && 724node -> src [1 ]-> ne [1 ] >=53 && // N >= 53 725node -> src [0 ]-> ne [1 ] %16 == 0 && // M % TILE_M 726node -> src [0 ]-> ne [0 ] %32 == 0 ) {// K % BLOCK_K (Q4_0 block) 727 728// Matrix engine for N >= 53; partial N (via n_cur-1) and errata padding are handled in-kernel. 729kernel_name = "mul_mat_Q4_0_matrix_engine" ; 730src0_type_name = "Q4_0" ; 731 732 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_Q4_0 && 733node -> src [1 ]-> type == GGML_TYPE_F32 ) { 734kernel_name = "mul_mat_Q4_0" ;// N < 53, or M % 16 != 0 or K % 32 != 0 735src0_type_name = "Q4_0" ; 736 737 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_Q8_0 && 738node -> src [1 ]-> type == GGML_TYPE_F32 ) { 739kernel_name = "mul_mat_Q8_0" ; 740src0_type_name = "Q8_0" ; 741 742 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F16 && 743node -> src [1 ]-> type == GGML_TYPE_F16 && node -> ne [0 ] %16 == 0 && node -> src [0 ]-> ne [0 ] %16 == 0 && 744node -> src [0 ]-> ne [1 ] %16 == 0 && node -> src [1 ]-> ne [0 ]!= 1 ) { 745kernel_name = "mul_mat_f16_matrix_engine" ; 746src0_type_name = "F16" ; 747 748 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F16 && 749 (node -> src [1 ]-> type == GGML_TYPE_F16 || node -> src [1 ]-> type == GGML_TYPE_F32 )) { 750kernel_name = "mul_mat_f16" ; 751src0_type_name = "F16" ; 752 753 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 && 754node -> src [1 ]-> type == GGML_TYPE_F32 && node -> ne [0 ] %16 == 0 && node -> src [0 ]-> ne [0 ] %16 == 0 && 755node -> src [0 ]-> ne [1 ] %16 == 0 && node -> src [1 ]-> ne [0 ]!= 1 ) {// GEMV is faster with the generic path 756 757kernel_name = "mul_mat_f32_matrix_engine" ; 758src0_type_name = "F32" ; 759 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 && 760 (node -> src [1 ]-> type == GGML_TYPE_F16 || node -> src [1 ]-> type == GGML_TYPE_F32 )) { 761kernel_name = "mul_mat_f32" ; 762src0_type_name = "F32" ; 763 }else { 764GGML_LOG_ERROR ("ET: MUL_MAT operation with unsupported types: dst=%s src0=%s src1=%s\n" , 765ggml_type_name (node -> type ),ggml_type_name (node -> src [0 ]-> type ), 766ggml_type_name (node -> src [1 ]-> type )); 767return false; 768 } 769 770ggml_et_binary_params params ; 771params .src0 = * node -> src [0 ];// weight matrix 772params .src1 = * node -> src [1 ];// activation matrix 773params .dst = * fused_dst ;// output (= add_node when fused, else node) 774 775ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 776bool cpu_comparison_active = false; 777if (mul_mat_cpu_compare_config .enabled ) { 778if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,fused_dst ,GGML_OP_MUL_MAT )) { 779cpu_comparison_active = true; 780 }else { 781GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for MUL_MAT operation\n" ); 782 } 783 } 784 785bool kernel_result ; 786if (node -> src [0 ]-> type == GGML_TYPE_Q8_0 ) { 787// Q8_0 kernel always takes the extended struct. bias.data is non-NULL 788// only on the fused path; otherwise the kernel skips the add entirely. 789ggml_et_mm_q8_params q8_params = {}; 790q8_params .src0 = params .src0 ; 791q8_params .src1 = params .src1 ; 792q8_params .dst = params .dst ; 793if (bias_tensor ) { 794q8_params .bias = * bias_tensor ; 795 } 796kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& q8_params ,sizeof (q8_params ),0xFFFFFFFF ); 797 }else { 798// Non-Q8 MM kernels don't yet support fused-add; the graph fuse check 799// already rejects non-Q8 pairs, so add_node is always nullptr here. 800kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 801 } 802 803// printf("Tensor error:"); 804// if (params.src0.data != NULL) 805// { 806// printf("Ptr OK\n"); 807// printf("node->data ptr = %p\n", node->data); 808// // if (once < 100){ 809// // // uint64_t * host_data = (uint64_t *) node->data; 810// // // printf("Tensor error: %lu\n", host_data[0]); 811 812// // // printf("Tensor error:"); 813// // once++; 814// // } 815// } 816 817// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 818if (cpu_comparison_active ) { 819if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,fused_dst ,& mul_mat_cpu_compare_config )) { 820GGML_LOG_WARN ("ET: CPU comparison failed for MUL_MAT operation\n" ); 821 } 822ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 823 } 824 825 { 826// Calculate actual FLOPs including batch/sequence dimensions 827// dst shape: [M, N, ne2, ne3] where M=ne[1], N=ne[0] 828int64_t m = node -> ne [1 ]; 829int64_t n = node -> ne [0 ]; 830int64_t k = node -> src [0 ]-> ne [0 ]; 831int64_t ne2 = node -> ne [2 ]; 832int64_t ne3 = node -> ne [3 ]; 833 834// Total FLOPs = (batch_size) * M * N * (2*K - 1) 835// Each MxN matrix-matrix multiply does M*N*(2*K-1) FLOPs 836// Broadcasting is handled by repeating computation, so count actual operations 837int64_t batch_size = ne2 * ne3 ; 838int64_t total_flops = batch_size * m * n * (2 * k - 1 ); 839 840char kernel_variant [64 ]; 841snprintf (kernel_variant ,sizeof (kernel_variant ),"%s_%sx%s" ,kernel_name ,src0_type_name , 842ggml_type_name (node -> src [1 ]-> type )); 843ET_PERF_END_EXT ("MUL_MAT" ,kernel_variant ,node ,"flops=%" PRId64 ,total_flops ); 844 } 845return kernel_result ; 846} 847 848bool ggml_et_op_mul_mat_id (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 849ET_PERF_START (); 850if (!dev_ctx || !node ) { 851GGML_LOG_ERROR ("ET: Invalid parameters for MUL_MAT_ID operation\n" ); 852return false; 853 } 854 855if (!node -> src [0 ]|| !node -> src [1 ]|| !node -> src [2 ]) { 856GGML_LOG_ERROR ("ET: MUL_MAT_ID operation missing required inputs\n" ); 857return false; 858 } 859 860const char * kernel_name ; 861const char * src0_type_name ; 862 863// Support Q8_0/Q4_0/F16/F32 x F32 -> F32 matrix multiplication with expert selection 864if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_Q8_0 && node -> src [1 ]-> type == GGML_TYPE_F32 && 865node -> src [2 ]-> type == GGML_TYPE_I32 ) { 866kernel_name = "mul_mat_id_Q8_0" ; 867src0_type_name = "Q8_0" ; 868 869 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_Q4_0 && 870node -> src [1 ]-> type == GGML_TYPE_F32 && node -> src [2 ]-> type == GGML_TYPE_I32 ) { 871kernel_name = "mul_mat_id_Q4_0" ; 872src0_type_name = "Q4_0" ; 873 874 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F16 && 875node -> src [1 ]-> type == GGML_TYPE_F32 && node -> src [2 ]-> type == GGML_TYPE_I32 ) { 876kernel_name = "mul_mat_id_f32" ; 877src0_type_name = "F16" ; 878 879 }else if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 && 880node -> src [1 ]-> type == GGML_TYPE_F32 && node -> src [2 ]-> type == GGML_TYPE_I32 ) { 881kernel_name = "mul_mat_id_f32" ; 882src0_type_name = "F32" ; 883 884 }else { 885GGML_LOG_ERROR ("ET: MUL_MAT_ID operation with unsupported types: dst=%s src0=%s src1=%s src2=%s\n" , 886ggml_type_name (node -> type ),ggml_type_name (node -> src [0 ]-> type ), 887ggml_type_name (node -> src [1 ]-> type ),ggml_type_name (node -> src [2 ]-> type )); 888return false; 889 } 890 891// Pack parameters - copy full tensor structures 892ggml_et_mul_mat_id_params params ; 893params .src0 = * node -> src [0 ];// Expert weight matrices (Q8_0/F16/F32) 894params .src1 = * node -> src [1 ];// Activation matrix (F32) 895params .src2 = * node -> src [2 ];// Expert indices (I32) 896params .dst = * node ;// Output matrix (F32) 897 898// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 899ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 900bool cpu_comparison_active = false; 901if (mul_mat_id_cpu_compare_config .enabled ) { 902if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_MUL_MAT_ID )) { 903cpu_comparison_active = true; 904 }else { 905GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for MUL_MAT_ID operation\n" ); 906 } 907 } 908 909// Launch ET kernel 910bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 911 912// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 913if (cpu_comparison_active ) { 914if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& mul_mat_id_cpu_compare_config )) { 915GGML_LOG_WARN ("ET: CPU comparison failed for MUL_MAT_ID operation\n" ); 916 } 917ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 918 } 919 920// Calculate FLOPs (approximate - similar to MUL_MAT but with expert routing overhead) 921// Each expert computation is similar to a MUL_MAT, but we only compute for selected experts 922int64_t K = node -> src [0 ]-> ne [0 ]; 923int64_t M = node -> src [0 ]-> ne [1 ]; 924int64_t n_expert_used = node -> src [2 ]-> ne [0 ]; 925int64_t batch = node -> src [2 ]-> ne [1 ]; 926 927int64_t total_flops = batch * n_expert_used * M * (2 * K - 1 ); 928 929char kernel_variant [64 ]; 930snprintf (kernel_variant ,sizeof (kernel_variant ),"%s_%sx%s" ,kernel_name ,src0_type_name , 931ggml_type_name (node -> src [1 ]-> type )); 932ET_PERF_END_EXT ("MUL_MAT_ID" ,kernel_variant ,node ,"flops=%" PRId64 "|n_expert=%lld|n_expert_used=%lld" , 933total_flops , (long long )node -> src [0 ]-> ne [2 ], (long long )n_expert_used ); 934 935return kernel_result ; 936} 937 938bool ggml_et_op_rope (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 939ET_PERF_START (); 940 941if (!dev_ctx || !node ) { 942GGML_LOG_ERROR ("ET: Invalid parameters for ROPE operation\n" ); 943return false; 944 } 945 946if (!node -> src [0 ]|| !node -> src [1 ]) { 947GGML_LOG_ERROR ("ET: ROPE operation missing required inputs\n" ); 948return false; 949 } 950 951const char * kernel_name ; 952 953if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 && node -> src [1 ]-> type == GGML_TYPE_I32 ) { 954kernel_name = "rope_f32" ; 955 }else { 956return false; 957 } 958 959// Pack parameters - copy full tensor structures and op_params 960ggml_et_rope_params params ; 961params .src0 = * node -> src [0 ];// F32 input tensor 962params .src1 = * node -> src [1 ];// I32 position tensor 963if (node -> src [2 ]) { 964params .src2 = * node -> src [2 ];// F32 frequency factors (optional) 965 }else { 966memset (& params .src2 ,0 ,sizeof (params .src2 ));// Zero if not provided 967 } 968params .dst = * node ;// F32 output tensor 969 970params .rope_params .n_past = ((const int32_t * )node -> op_params )[0 ]; 971params .rope_params .n_dims = ((const int32_t * )node -> op_params )[1 ]; 972params .rope_params .mode = ((const int32_t * )node -> op_params )[2 ]; 973params .rope_params .n_ctx = ((const int32_t * )node -> op_params )[3 ]; 974params .rope_params .n_ctx_orig = ((const int32_t * )node -> op_params )[4 ]; 975memcpy (& params .rope_params .freq_base , (const int32_t * )node -> op_params + 5 ,sizeof (float )); 976memcpy (& params .rope_params .freq_scale , (const int32_t * )node -> op_params + 6 ,sizeof (float )); 977memcpy (& params .rope_params .ext_factor , (const int32_t * )node -> op_params + 7 ,sizeof (float )); 978memcpy (& params .rope_params .attn_factor , (const int32_t * )node -> op_params + 8 ,sizeof (float )); 979memcpy (& params .rope_params .beta_fast , (const int32_t * )node -> op_params + 9 ,sizeof (float )); 980memcpy (& params .rope_params .beta_slow , (const int32_t * )node -> op_params + 10 ,sizeof (float )); 981if (params .rope_params .mode & GGML_ROPE_TYPE_MROPE ) { 982memcpy (params .rope_params .sections , (const int32_t * )node -> op_params + 11 ,sizeof (int32_t )* 4 ); 983 }else { 984memset (params .rope_params .sections ,0 ,sizeof (params .rope_params .sections )); 985 } 986 987// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 988ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 989bool cpu_comparison_active = false; 990if (rope_cpu_compare_config .enabled ) { 991GGML_LOG_DEBUG ("ET: Initializing CPU comparison for ROPE operation\n" ); 992if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_ROPE )) { 993cpu_comparison_active = true; 994 }else { 995GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for ROPE operation\n" ); 996 } 997 } 998 999bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1000 1001// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1002if (cpu_comparison_active ) { 1003if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& rope_cpu_compare_config )) { 1004GGML_LOG_WARN ("ET: CPU comparison failed for ROPE operation\n" ); 1005 } 1006ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1007 } 1008 1009ET_PERF_END_EXT ("ROPE" ,kernel_name ,node ,"mode=0x%x|n_dims=%d|freq_base=%.2f|freq_scale=%.2f" , 1010params .rope_params .mode ,params .rope_params .n_dims , (double )params .rope_params .freq_base , 1011 (double )params .rope_params .freq_scale ); 1012return kernel_result ; 1013} 1014 1015bool ggml_et_op_rms_norm (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1016ET_PERF_START (); 1017 1018if (!dev_ctx || !node ) { 1019GGML_LOG_ERROR ("ET: Invalid parameters for RMS_NORM operation\n" ); 1020return false; 1021 } 1022 1023if (!node -> src [0 ]) { 1024GGML_LOG_ERROR ("ET: RMS_NORM operation missing required input\n" ); 1025return false; 1026 } 1027 1028const char * kernel_name ; 1029 1030if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 ) { 1031kernel_name = "rms_norm_f32" ; 1032 1033 }else { 1034GGML_LOG_ERROR ("ET: RMS_NORM operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 1035ggml_type_name (node -> src [0 ]-> type )); 1036return false; 1037 } 1038 1039float eps ; 1040memcpy (& eps ,node -> op_params ,sizeof (float )); 1041 1042ggml_et_rms_norm_params params ; 1043params .src0 = * node -> src [0 ];// F32 input tensor 1044params .dst = * node ;// F32 output tensor 1045params .eps = eps ;// Epsilon parameter for numerical stability 1046 1047// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1048ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1049bool cpu_comparison_active = false; 1050if (rms_norm_cpu_compare_config .enabled ) { 1051if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_RMS_NORM )) { 1052cpu_comparison_active = true; 1053 }else { 1054GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for RMS_NORM operation\n" ); 1055 } 1056 } 1057 1058bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1059 1060// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1061if (cpu_comparison_active ) { 1062if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& rms_norm_cpu_compare_config )) { 1063GGML_LOG_WARN ("ET: CPU comparison failed for RMS_NORM operation\n" ); 1064 } 1065ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1066 } 1067 1068ET_PERF_END_EXT ("RMS_NORM" ,kernel_name ,node ,"eps=%.6f" , (double )eps ); 1069return kernel_result ; 1070} 1071 1072bool ggml_et_op_norm (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1073ET_PERF_START (); 1074 1075if (!dev_ctx || !node ) { 1076GGML_LOG_ERROR ("ET: Invalid parameters for NORM operation\n" ); 1077return false; 1078 } 1079 1080if (!node -> src [0 ]) { 1081GGML_LOG_ERROR ("ET: NORM operation missing required input\n" ); 1082return false; 1083 } 1084 1085const char * kernel_name ; 1086 1087if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 ) { 1088kernel_name = "norm_f32" ; 1089 1090 }else { 1091GGML_LOG_ERROR ("ET: NORM operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 1092ggml_type_name (node -> src [0 ]-> type )); 1093return false; 1094 } 1095 1096float eps ; 1097memcpy (& eps ,node -> op_params ,sizeof (float )); 1098 1099ggml_et_norm_params params ; 1100params .src0 = * node -> src [0 ];// F32 input tensor 1101params .dst = * node ;// F32 output tensor 1102params .eps = eps ;// Epsilon parameter for numerical stability 1103 1104// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1105ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1106bool cpu_comparison_active = false; 1107if (norm_cpu_compare_config .enabled ) { 1108if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_NORM )) { 1109cpu_comparison_active = true; 1110 }else { 1111GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for NORM operation\n" ); 1112 } 1113 } 1114 1115bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1116 1117// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1118if (cpu_comparison_active ) { 1119if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& norm_cpu_compare_config )) { 1120GGML_LOG_WARN ("ET: CPU comparison failed for NORM operation\n" ); 1121 } 1122ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1123 } 1124 1125ET_PERF_END_EXT ("NORM" ,kernel_name ,node ,"eps=%.6f" , (double )eps ); 1126return kernel_result ; 1127} 1128 1129bool ggml_et_op_l2_norm (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1130ET_PERF_START (); 1131 1132if (!dev_ctx || !node ) { 1133GGML_LOG_ERROR ("ET: Invalid parameters for L2_NORM operation\n" ); 1134return false; 1135 } 1136 1137if (!node -> src [0 ]) { 1138GGML_LOG_ERROR ("ET: L2_NORM operation missing required input\n" ); 1139return false; 1140 } 1141 1142const char * kernel_name ; 1143 1144if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 ) { 1145kernel_name = "l2_norm_f32" ; 1146 1147 }else { 1148GGML_LOG_ERROR ("ET: L2_NORM operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 1149ggml_type_name (node -> src [0 ]-> type )); 1150return false; 1151 } 1152 1153float eps ; 1154memcpy (& eps ,node -> op_params ,sizeof (float )); 1155 1156ggml_et_l2_norm_params params ; 1157params .src0 = * node -> src [0 ];// F32 input tensor 1158params .dst = * node ;// F32 output tensor 1159params .eps = eps ;// Epsilon parameter for numerical stability 1160 1161// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1162ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1163bool cpu_comparison_active = false; 1164if (l2_norm_cpu_compare_config .enabled ) { 1165if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_L2_NORM )) { 1166cpu_comparison_active = true; 1167 }else { 1168GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for L2_NORM operation\n" ); 1169 } 1170 } 1171 1172bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1173 1174// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1175if (cpu_comparison_active ) { 1176if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& l2_norm_cpu_compare_config )) { 1177GGML_LOG_WARN ("ET: CPU comparison failed for L2_NORM operation\n" ); 1178 } 1179ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1180 } 1181 1182ET_PERF_END_EXT ("L2_NORM" ,kernel_name ,node ,"eps=%.6f" , (double )eps ); 1183return kernel_result ; 1184} 1185 1186bool ggml_et_op_group_norm (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1187ET_PERF_START (); 1188 1189if (!dev_ctx || !node ) { 1190GGML_LOG_ERROR ("ET: Invalid parameters for GROUP_NORM operation\n" ); 1191return false; 1192 } 1193 1194if (!node -> src [0 ]) { 1195GGML_LOG_ERROR ("ET: GROUP_NORM operation missing required input\n" ); 1196return false; 1197 } 1198 1199if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 1200GGML_LOG_ERROR ("ET: GROUP_NORM operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 1201ggml_type_name (node -> src [0 ]-> type )); 1202return false; 1203 } 1204 1205const int32_t n_groups = ggml_get_op_params_i32 (node ,0 ); 1206float eps ; 1207memcpy (& eps , (const float * )node -> op_params + 1 ,sizeof (float )); 1208 1209ggml_et_group_norm_params params ; 1210params .src0 = * node -> src [0 ]; 1211params .dst = * node ; 1212params .n_groups = n_groups ; 1213params .eps = eps ; 1214 1215ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1216bool cpu_comparison_active = false; 1217if (group_norm_cpu_compare_config .enabled ) { 1218if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_GROUP_NORM )) { 1219cpu_comparison_active = true; 1220 }else { 1221GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for GROUP_NORM operation\n" ); 1222 } 1223 } 1224 1225bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"group_norm_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 1226 1227if (cpu_comparison_active ) { 1228if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& group_norm_cpu_compare_config )) { 1229GGML_LOG_WARN ("ET: CPU comparison failed for GROUP_NORM operation\n" ); 1230 } 1231ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1232 } 1233 1234ET_PERF_END_EXT ("GROUP_NORM" ,"group_norm_f32" ,node ,"eps=%.6f|n_groups=%d" , (double )eps ,n_groups ); 1235return kernel_result ; 1236} 1237 1238bool ggml_et_op_im2col (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1239ET_PERF_START (); 1240 1241if (!dev_ctx || !node ) { 1242GGML_LOG_ERROR ("ET: Invalid parameters for IM2COL operation\n" ); 1243return false; 1244 } 1245 1246if (!node -> src [0 ]|| !node -> src [1 ]) { 1247GGML_LOG_ERROR ("ET: IM2COL operation missing required inputs\n" ); 1248return false; 1249 } 1250 1251const bool supported_types = 1252 (node -> type == GGML_TYPE_F32 && node -> src [1 ]-> type == GGML_TYPE_F32 )|| 1253 (node -> type == GGML_TYPE_F16 && (node -> src [1 ]-> type == GGML_TYPE_F16 || node -> src [1 ]-> type == GGML_TYPE_F32 )); 1254 1255if (!supported_types ) { 1256GGML_LOG_ERROR ("ET: IM2COL operation with unsupported types: dst=%s src1=%s\n" ,ggml_type_name (node -> type ), 1257ggml_type_name (node -> src [1 ]-> type )); 1258return false; 1259 } 1260 1261ggml_et_im2col_params params ; 1262params .src0 = * node -> src [0 ]; 1263params .src1 = * node -> src [1 ]; 1264params .dst = * node ; 1265 1266ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1267bool cpu_comparison_active = false; 1268if (im2col_cpu_compare_config .enabled ) { 1269if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_IM2COL )) { 1270cpu_comparison_active = true; 1271 }else { 1272GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for IM2COL operation\n" ); 1273 } 1274 } 1275 1276bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"im2col" ,& params ,sizeof (params ),0xFFFFFFFF ); 1277 1278if (cpu_comparison_active ) { 1279if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& im2col_cpu_compare_config )) { 1280GGML_LOG_WARN ("ET: CPU comparison failed for IM2COL operation\n" ); 1281 } 1282ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1283 } 1284 1285ET_PERF_END ("IM2COL" ,"im2col" ,node ); 1286return kernel_result ; 1287} 1288 1289bool ggml_et_op_conv_2d (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1290ET_PERF_START (); 1291 1292if (!dev_ctx || !node ) { 1293return false; 1294 } 1295if (!node -> src [0 ]|| !node -> src [1 ]) { 1296return false; 1297 } 1298if (!node -> data || !node -> src [0 ]-> data || !node -> src [1 ]-> data ) { 1299return false; 1300 } 1301 1302// Kernel constraints (mirror supports_op; recheck here as a guard). 1303const ggml_tensor * flt = node -> src [0 ];// [Kw, Kh, Cin, Cout] 1304const ggml_tensor * in = node -> src [1 ];// [W, H, Cin, N] 1305if (node -> type != GGML_TYPE_F32 || flt -> type != GGML_TYPE_F32 || in -> type != GGML_TYPE_F32 ) { 1306return false; 1307 } 1308 1309const int32_t s0 = ggml_get_op_params_i32 (node ,0 ); 1310const int32_t s1 = ggml_get_op_params_i32 (node ,1 ); 1311const int32_t p0 = ggml_get_op_params_i32 (node ,2 ); 1312const int32_t p1 = ggml_get_op_params_i32 (node ,3 ); 1313const int32_t d0 = ggml_get_op_params_i32 (node ,4 ); 1314const int32_t d1 = ggml_get_op_params_i32 (node ,5 ); 1315 1316if (s0 < 1 || s1 < 1 ) { 1317return false; 1318 } 1319if (d0 != 1 || d1 != 1 ) { 1320return false; 1321 } 1322if (flt -> ne [2 ] %16 != 0 || flt -> ne [3 ] %16 != 0 ) { 1323return false; 1324 } 1325if (in -> ne [3 ]!= 1 ) { 1326return false; 1327 } 1328if (node -> ne [0 ] <=0 ) { 1329return false;// OW > 0 (any width OK; staging path handles non-16) 1330 } 1331 (void )p0 ; 1332 (void )p1 ; 1333 1334ggml_et_binary_params params ; 1335params .src0 = * node -> src [0 ]; 1336params .src1 = * node -> src [1 ]; 1337params .dst = * node ; 1338 1339bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"conv_2d_f32_me" ,& params ,sizeof (params ),0xFFFFFFFFu ); 1340 1341ET_PERF_END ("CONV_2D" ,"conv_2d_f32_me" ,node ); 1342return kernel_result ; 1343} 1344 1345bool ggml_et_op_softmax (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1346ET_PERF_START (); 1347 1348if (!dev_ctx || !node ) { 1349GGML_LOG_ERROR ("ET: Invalid parameters for SOFTMAX operation\n" ); 1350return false; 1351 } 1352 1353if (!node -> src [0 ]) { 1354GGML_LOG_ERROR ("ET: SOFTMAX operation missing required input\n" ); 1355return false; 1356 } 1357 1358const char * kernel_name ; 1359 1360if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 ) { 1361kernel_name = "softmax_f32" ; 1362 1363 }else { 1364GGML_LOG_ERROR ("ET: SOFTMAX operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 1365ggml_type_name (node -> src [0 ]-> type )); 1366return false; 1367 } 1368 1369// Validate contiguity requirements 1370if (!ggml_is_contiguous (node )) { 1371GGML_LOG_ERROR ("ET: SOFTMAX operation requires contiguous destination tensor\n" ); 1372return false; 1373 } 1374 1375if (!ggml_is_contiguous (node -> src [0 ])) { 1376GGML_LOG_ERROR ("ET: SOFTMAX operation requires contiguous source tensor\n" ); 1377return false; 1378 } 1379 1380// Check optional mask tensor 1381if (node -> src [1 ]) { 1382if (node -> src [1 ]-> type != GGML_TYPE_F32 ) { 1383GGML_LOG_ERROR ("ET: SOFTMAX operation with unsupported mask type: %s (F32 required)\n" , 1384ggml_type_name (node -> src [1 ]-> type )); 1385return false; 1386 } 1387if (!ggml_is_contiguous (node -> src [1 ])) { 1388GGML_LOG_ERROR ("ET: SOFTMAX operation requires contiguous mask tensor\n" ); 1389return false; 1390 } 1391 } 1392 1393// Check optional sinks tensor 1394if (node -> src [2 ]) { 1395if (node -> src [2 ]-> type != GGML_TYPE_F32 ) { 1396GGML_LOG_ERROR ("ET: SOFTMAX operation with unsupported sinks type: %s (F32 required)\n" , 1397ggml_type_name (node -> src [2 ]-> type )); 1398return false; 1399 } 1400if (!ggml_is_contiguous (node -> src [2 ])) { 1401GGML_LOG_ERROR ("ET: SOFTMAX operation requires contiguous sinks tensor\n" ); 1402return false; 1403 } 1404 } 1405 1406// Extract scale and max_bias from op_params 1407float scale = 1.0f ; 1408float max_bias = 0.0f ; 1409if (node -> op_params ) { 1410memcpy (& scale , (const float * )node -> op_params + 0 ,sizeof (float )); 1411memcpy (& max_bias , (const float * )node -> op_params + 1 ,sizeof (float )); 1412 } 1413 1414ggml_et_softmax_params params ; 1415params .src0 = * node -> src [0 ];// F32 input tensor 1416if (node -> src [1 ]) { 1417params .src1 = * node -> src [1 ];// F32 mask tensor 1418 }else { 1419memset (& params .src1 ,0 ,sizeof (params .src1 ));// Zero if no mask 1420 } 1421if (node -> src [2 ]) { 1422params .src2 = * node -> src [2 ];// F32 sinks tensor 1423 }else { 1424memset (& params .src2 ,0 ,sizeof (params .src2 ));// Zero if no sinks 1425 } 1426params .dst = * node ;// F32 output tensor 1427params .scale = scale ;// Scale factor 1428params .max_bias = max_bias ;// ALiBi bias 1429 1430// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1431ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1432bool cpu_comparison_active = false; 1433if (softmax_cpu_compare_config .enabled ) { 1434if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_SOFT_MAX )) { 1435cpu_comparison_active = true; 1436 }else { 1437GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for SOFTMAX operation\n" ); 1438 } 1439 } 1440 1441bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1442 1443// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1444if (cpu_comparison_active ) { 1445if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& softmax_cpu_compare_config )) { 1446GGML_LOG_WARN ("ET: CPU comparison failed for SOFTMAX operation\n" ); 1447 } 1448ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1449 } 1450 1451ET_PERF_END_EXT ("SOFTMAX" ,kernel_name ,node ,"scale=%.6f|max_bias=%.6f|has_mask=%s" , (double )scale , 1452 (double )max_bias ,node -> src [1 ] ?"yes" :"no" ); 1453return kernel_result ; 1454} 1455 1456bool ggml_et_op_flash_attn_ext (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1457ET_PERF_START (); 1458 1459if (!dev_ctx || !node ) { 1460GGML_LOG_ERROR ("ET: Invalid parameters for FLASH_ATTN_EXT operation\n" ); 1461return false; 1462 } 1463 1464if (!node -> src [0 ]|| !node -> src [1 ]|| !node -> src [2 ]) { 1465GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT operation missing required inputs\n" ); 1466return false; 1467 } 1468 1469if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 1470GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT requires F32 Q and dst, got dst=%s q=%s\n" ,ggml_type_name (node -> type ), 1471ggml_type_name (node -> src [0 ]-> type )); 1472return false; 1473 } 1474 1475// K and V can be F16 or F32 1476if ((node -> src [1 ]-> type != GGML_TYPE_F32 && node -> src [1 ]-> type != GGML_TYPE_F16 )|| 1477 (node -> src [2 ]-> type != GGML_TYPE_F32 && node -> src [2 ]-> type != GGML_TYPE_F16 )) { 1478GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT K/V must be F16 or F32, got k=%s v=%s\n" ,ggml_type_name (node -> src [1 ]-> type ), 1479ggml_type_name (node -> src [2 ]-> type )); 1480return false; 1481 } 1482 1483if (node -> src [4 ]!= nullptr ) { 1484GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT baseline kernel does not support sinks\n" ); 1485return false; 1486 } 1487 1488// Mask is optional; if present must be F16 or F32 1489if (node -> src [3 ]!= nullptr && node -> src [3 ]-> type != GGML_TYPE_F32 && node -> src [3 ]-> type != GGML_TYPE_F16 ) { 1490GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT mask must be F16 or F32, got %s\n" ,ggml_type_name (node -> src [3 ]-> type )); 1491return false; 1492 } 1493 1494// Q and dst must be row-contiguous F32 1495if (!ggml_is_contiguous_rows (node )|| !ggml_is_contiguous_rows (node -> src [0 ])) { 1496GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT requires row-contiguous Q and dst\n" ); 1497return false; 1498 } 1499 1500if (node -> nb [0 ]!= sizeof (float )|| node -> src [0 ]-> nb [0 ]!= sizeof (float )) { 1501GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT requires contiguous F32 rows for Q and dst\n" ); 1502return false; 1503 } 1504 1505// K/V must have element-sized stride in dim 0 1506const size_t k_elem = node -> src [1 ]-> type == GGML_TYPE_F16 ?2 :4 ; 1507const size_t v_elem = node -> src [2 ]-> type == GGML_TYPE_F16 ?2 :4 ; 1508if (node -> src [1 ]-> nb [0 ]!= k_elem || node -> src [2 ]-> nb [0 ]!= v_elem ) { 1509GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT K/V must have element-sized stride in dim 0\n" ); 1510return false; 1511 } 1512 1513float scale = 1.0f ; 1514float max_bias = 0.0f ; 1515float logit_softcap = 0.0f ; 1516memcpy (& scale , (const float * )node -> op_params + 0 ,sizeof (scale )); 1517memcpy (& max_bias , (const float * )node -> op_params + 1 ,sizeof (max_bias )); 1518memcpy (& logit_softcap , (const float * )node -> op_params + 2 ,sizeof (logit_softcap )); 1519 1520if (max_bias != 0.0f || logit_softcap != 0.0f ) { 1521GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT baseline kernel does not support max_bias or logit_softcap\n" ); 1522return false; 1523 } 1524 1525const ggml_prec prec = ggml_flash_attn_ext_get_prec (node ); 1526if (prec != GGML_PREC_F32 && prec != GGML_PREC_DEFAULT ) { 1527GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT baseline kernel only supports F32 precision\n" ); 1528return false; 1529 } 1530 1531// dk must match between Q and K; dv must match between V and dst 1532if (node -> src [0 ]-> ne [0 ]!= node -> src [1 ]-> ne [0 ]) { 1533GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT dk mismatch: Q=%lld K=%lld\n" , (long long )node -> src [0 ]-> ne [0 ], 1534 (long long )node -> src [1 ]-> ne [0 ]); 1535return false; 1536 } 1537 1538if (node -> src [2 ]-> ne [0 ]!= node -> ne [0 ]) { 1539GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT dv mismatch: V=%lld dst=%lld\n" , (long long )node -> src [2 ]-> ne [0 ], 1540 (long long )node -> ne [0 ]); 1541return false; 1542 } 1543 1544if (node -> src [2 ]-> ne [0 ]> 512 ) { 1545GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT dv=%lld exceeds maximum 512\n" , (long long )node -> src [2 ]-> ne [0 ]); 1546return false; 1547 } 1548 1549if (node -> src [0 ]-> ne [0 ]> 512 ) { 1550GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT dk=%lld exceeds maximum 512\n" , (long long )node -> src [0 ]-> ne [0 ]); 1551return false; 1552 } 1553 1554// GQA: n_head_q must be a multiple of n_head_kv 1555const int64_t nhq = node -> src [0 ]-> ne [2 ]; 1556const int64_t nhk = node -> src [1 ]-> ne [2 ]; 1557if (nhq %nhk != 0 ) { 1558GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT n_head_q (%lld) not divisible by n_head_kv (%lld)\n" , (long long )nhq , 1559 (long long )nhk ); 1560return false; 1561 } 1562 1563// K and V must have matching sequence length, heads, and batch dims 1564if (node -> src [1 ]-> ne [1 ]!= node -> src [2 ]-> ne [1 ]|| node -> src [1 ]-> ne [2 ]!= node -> src [2 ]-> ne [2 ]|| 1565node -> src [1 ]-> ne [3 ]!= node -> src [2 ]-> ne [3 ]) { 1566GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT K/V shape mismatch\n" ); 1567return false; 1568 } 1569 1570// dst layout checks: [dv, nhq, nq, no] 1571if (node -> src [0 ]-> ne [1 ]!= node -> ne [2 ]|| node -> src [0 ]-> ne [2 ]!= node -> ne [1 ]|| 1572node -> src [0 ]-> ne [3 ]!= node -> ne [3 ]) { 1573GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT dst shape mismatch\n" ); 1574return false; 1575 } 1576 1577// Batch dims: Q batch must match K batch 1578if (node -> src [0 ]-> ne [3 ]!= node -> src [1 ]-> ne [3 ]) { 1579GGML_LOG_ERROR ("ET: FLASH_ATTN_EXT batch dimension mismatch\n" ); 1580return false; 1581 } 1582 1583ggml_et_flash_attn_ext_params params ; 1584memset (& params ,0 ,sizeof (params )); 1585params .src0 = * node -> src [0 ]; 1586params .src1 = * node -> src [1 ]; 1587params .src2 = * node -> src [2 ]; 1588if (node -> src [3 ]!= nullptr ) { 1589params .mask = * node -> src [3 ]; 1590params .has_mask = 1 ; 1591 } 1592params .dst = * node ; 1593params .scale = scale ; 1594 1595// Use matrix engine kernel when K/V are F16 and dk is a multiple of 32 1596const char * kernel_name ; 1597if (node -> src [1 ]-> type == GGML_TYPE_F16 && node -> src [2 ]-> type == GGML_TYPE_F16 && (node -> src [0 ]-> ne [0 ] %32 )== 0 ) { 1598kernel_name = "flash_attn_ext_f16_me" ; 1599 }else { 1600kernel_name = "flash_attn_ext_f32" ; 1601 } 1602 1603const bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1604 1605ET_PERF_END_EXT ("FLASH_ATTN_EXT" ,kernel_name ,node ,"scale=%.6f" , (double )scale ); 1606return kernel_result ; 1607} 1608 1609bool ggml_et_op_get_rows (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1610ET_PERF_START (); 1611 1612if (!dev_ctx || !node ) { 1613GGML_LOG_ERROR ("ET: Invalid parameters for GET_ROWS operation\n" ); 1614return false; 1615 } 1616 1617if (!node -> src [0 ]|| !node -> src [1 ]) { 1618GGML_LOG_ERROR ("ET: GET_ROWS operation missing required inputs\n" ); 1619return false; 1620 } 1621 1622const char * kernel_name ; 1623 1624if (node -> type == GGML_TYPE_F32 && node -> src [1 ]-> type == GGML_TYPE_I32 && 1625 (node -> src [0 ]-> type == GGML_TYPE_F32 || node -> src [0 ]-> type == GGML_TYPE_F16 || 1626node -> src [0 ]-> type == GGML_TYPE_Q4_0 || node -> src [0 ]-> type == GGML_TYPE_Q8_0 || 1627node -> src [0 ]-> type == GGML_TYPE_Q4_K )) { 1628kernel_name = "get_rows_f32" ; 1629 1630 }else { 1631GGML_LOG_ERROR ("ET: GET_ROWS operation with unsupported types: dst=%s src0=%s src1=%s\n" , 1632ggml_type_name (node -> type ),ggml_type_name (node -> src [0 ]-> type ), 1633ggml_type_name (node -> src [1 ]-> type )); 1634return false; 1635 } 1636 1637// Validate contiguity requirements 1638if (!ggml_is_contiguous (node )) { 1639GGML_LOG_ERROR ("ET: GET_ROWS operation requires contiguous destination tensor\n" ); 1640return false; 1641 } 1642 1643if (!ggml_is_contiguous (node -> src [0 ])) { 1644GGML_LOG_ERROR ("ET: GET_ROWS operation requires contiguous data tensor\n" ); 1645return false; 1646 } 1647 1648if (!ggml_is_contiguous (node -> src [1 ])) { 1649GGML_LOG_ERROR ("ET: GET_ROWS operation requires contiguous indices tensor\n" ); 1650return false; 1651 } 1652 1653// Validate dimension constraints from ggml implementation 1654if (node -> src [0 ]-> ne [2 ]!= node -> src [1 ]-> ne [1 ]|| node -> src [1 ]-> ne [3 ]!= 1 ) { 1655GGML_LOG_ERROR ( 1656"ET: GET_ROWS operation dimension constraint failed: src0.ne[2]=%lld != src1.ne[1]=%lld or src1.ne[3]=%lld " 1657"!= 1\n" , 1658 (long long )node -> src [0 ]-> ne [2 ], (long long )node -> src [1 ]-> ne [1 ], (long long )node -> src [1 ]-> ne [3 ]); 1659return false; 1660 } 1661 1662ggml_et_get_rows_params params ; 1663params .src0 = * node -> src [0 ];// Data tensor (F32 or Q8_0) 1664params .src1 = * node -> src [1 ];// Indices tensor (I32) 1665params .dst = * node ;// Output tensor (F32) 1666 1667// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1668ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1669bool cpu_comparison_active = false; 1670if (get_rows_cpu_compare_config .enabled ) { 1671if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_GET_ROWS )) { 1672cpu_comparison_active = true; 1673 }else { 1674GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for GET_ROWS operation\n" ); 1675 } 1676 } 1677 1678bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1679 1680// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1681if (cpu_comparison_active ) { 1682if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& get_rows_cpu_compare_config )) { 1683GGML_LOG_WARN ("ET: CPU comparison failed for GET_ROWS operation\n" ); 1684 } 1685ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1686 } 1687 1688ET_PERF_END ("GET_ROWS" ,kernel_name ,node ); 1689return kernel_result ; 1690} 1691 1692bool ggml_et_op_cont (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1693ET_PERF_START (); 1694 1695// Validate source tensor exists 1696if (!node -> src [0 ]) { 1697GGML_LOG_ERROR ("ET: CONT operation missing source tensor\n" ); 1698return false; 1699 } 1700 1701// Validate types match (input and output must be same type) 1702if (node -> type != node -> src [0 ]-> type ) { 1703GGML_LOG_ERROR ("ET: CONT operation type mismatch: src=%s dst=%s\n" ,ggml_type_name (node -> src [0 ]-> type ), 1704ggml_type_name (node -> type )); 1705return false; 1706 } 1707 1708// Validate supported types 1709if (node -> type != GGML_TYPE_F32 && node -> type != GGML_TYPE_F16 ) { 1710GGML_LOG_ERROR ("ET: CONT operation unsupported type: %s (only F32 and F16 supported)\n" , 1711ggml_type_name (node -> type )); 1712return false; 1713 } 1714 1715// Validate contiguity - output must be contiguous, input can be non-contiguous 1716if (!ggml_is_contiguous (node )) { 1717GGML_LOG_ERROR ("ET: CONT operation requires contiguous output tensor\n" ); 1718return false; 1719 } 1720 1721// Select kernel based on type 1722const char * kernel_name ; 1723if (node -> type == GGML_TYPE_F32 ) { 1724kernel_name = "cont_f32" ; 1725 }else if (node -> type == GGML_TYPE_F16 ) { 1726kernel_name = "cont_f16" ; 1727 }else { 1728GGML_LOG_ERROR ("ET: CONT operation with unsupported type: %s\n" ,ggml_type_name (node -> type )); 1729return false; 1730 } 1731 1732ggml_et_cont_params params ; 1733params .src0 = * node -> src [0 ];// Input tensor (potentially non-contiguous) 1734params .dst = * node ;// Output tensor (contiguous) 1735 1736// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1737ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1738bool cpu_comparison_active = false; 1739if (cont_cpu_compare_config .enabled ) { 1740if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_CONT )) { 1741cpu_comparison_active = true; 1742 }else { 1743GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for CONT operation\n" ); 1744 } 1745 } 1746 1747bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1748 1749// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1750if (cpu_comparison_active ) { 1751if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& cont_cpu_compare_config )) { 1752GGML_LOG_WARN ("ET: CPU comparison failed for CONT operation\n" ); 1753 } 1754ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1755 } 1756 1757ET_PERF_END ("CONT" ,kernel_name ,node ); 1758return kernel_result ; 1759} 1760 1761bool ggml_et_op_cumsum (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1762ET_PERF_START (); 1763 1764if (!dev_ctx || !node || !node -> src [0 ]) { 1765GGML_LOG_ERROR ("ET: Invalid parameters for CUMSUM operation\n" ); 1766return false; 1767 } 1768 1769if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 1770GGML_LOG_ERROR ("ET: CUMSUM operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 1771ggml_type_name (node -> src [0 ]-> type )); 1772return false; 1773 } 1774 1775const char * kernel_name = "cumsum_f32" ; 1776 1777ggml_et_cumsum_params params ; 1778params .src0 = * node -> src [0 ]; 1779params .dst = * node ; 1780 1781ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1782bool cpu_comparison_active = false; 1783if (cumsum_cpu_compare_config .enabled ) { 1784if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_CUMSUM )) { 1785cpu_comparison_active = true; 1786 }else { 1787GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for CUMSUM operation\n" ); 1788 } 1789 } 1790 1791bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1792 1793if (cpu_comparison_active ) { 1794if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& cumsum_cpu_compare_config )) { 1795GGML_LOG_WARN ("ET: CPU comparison failed for CUMSUM operation\n" ); 1796 } 1797ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1798 } 1799 1800ET_PERF_END ("CUMSUM" ,kernel_name ,node ); 1801return kernel_result ; 1802} 1803 1804bool ggml_et_op_cpy (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1805ET_PERF_START (); 1806 1807// CPY copies data from src[0] into the layout of dst (which matches src[1]) 1808// For same-type with contiguous dst, this is identical to CONT 1809if (!node -> src [0 ]) { 1810GGML_LOG_ERROR ("ET: CPY operation missing source tensor\n" ); 1811return false; 1812 } 1813 1814// Scalar / zero-element special path: if any dimension is 0, nothing to copy 1815const int64_t nelements = node -> ne [0 ]* node -> ne [1 ]* node -> ne [2 ]* node -> ne [3 ]; 1816if (nelements == 0 ) { 1817GGML_LOG_DEBUG ("ET: CPY no-op (zero elements): ne=[%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 "]\n" , 1818node -> ne [0 ],node -> ne [1 ],node -> ne [2 ],node -> ne [3 ]); 1819ET_PERF_END ("CPY" ,"noop" ,node ); 1820return true; 1821 } 1822 1823// Only F32 and F16 supported for dst 1824if (node -> type != GGML_TYPE_F32 && node -> type != GGML_TYPE_F16 ) { 1825GGML_LOG_ERROR ("ET: CPY unsupported dst type: %s\n" ,ggml_type_name (node -> type )); 1826return false; 1827 } 1828 1829// Select kernel based on src/dst type combination 1830const char * kernel_name ; 1831if (node -> src [0 ]-> type == GGML_TYPE_F32 && node -> type == GGML_TYPE_F32 ) { 1832kernel_name = "cont_f32" ; 1833 }else if (node -> src [0 ]-> type == GGML_TYPE_F16 && node -> type == GGML_TYPE_F16 ) { 1834kernel_name = "cont_f16" ; 1835 }else if (node -> src [0 ]-> type == GGML_TYPE_F32 && node -> type == GGML_TYPE_F16 ) { 1836kernel_name = "cpy_f32_f16" ; 1837 }else { 1838GGML_LOG_ERROR ("ET: CPY unsupported type combination: src=%s dst=%s\n" ,ggml_type_name (node -> src [0 ]-> type ), 1839ggml_type_name (node -> type )); 1840return false; 1841 } 1842 1843ggml_et_cont_params params ; 1844params .src0 = * node -> src [0 ]; 1845params .dst = * node ; 1846 1847// CPU comparison for debugging 1848ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1849bool cpu_comparison_active = false; 1850if (cont_cpu_compare_config .enabled ) { 1851if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_CPY )) { 1852cpu_comparison_active = true; 1853 }else { 1854GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for CPY operation\n" ); 1855 } 1856 } 1857 1858bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1859 1860if (cpu_comparison_active ) { 1861if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& cont_cpu_compare_config )) { 1862GGML_LOG_WARN ("ET: CPU comparison failed for CPY operation\n" ); 1863 } 1864ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1865 } 1866 1867ET_PERF_END ("CPY" ,kernel_name ,node ); 1868return kernel_result ; 1869} 1870 1871bool ggml_et_op_concat (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1872ET_PERF_START (); 1873 1874if (!dev_ctx || !node ) { 1875GGML_LOG_ERROR ("ET: Invalid parameters for CONCAT operation\n" ); 1876return false; 1877 } 1878 1879if (!node -> src [0 ]|| !node -> src [1 ]) { 1880GGML_LOG_ERROR ("ET: CONCAT operation missing required inputs\n" ); 1881return false; 1882 } 1883 1884const char * kernel_name ; 1885 1886if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 && node -> src [1 ]-> type == GGML_TYPE_F32 ) { 1887kernel_name = "concat_f32" ; 1888 1889 }else { 1890GGML_LOG_ERROR ("ET: CONCAT operation with unsupported types: dst=%s src0=%s src1=%s\n" , 1891ggml_type_name (node -> type ),ggml_type_name (node -> src [0 ]-> type ), 1892ggml_type_name (node -> src [1 ]-> type )); 1893return false; 1894 } 1895 1896int32_t dim ; 1897memcpy (& dim ,node -> op_params ,sizeof (int32_t )); 1898 1899ggml_et_concat_params params ; 1900params .src0 = * node -> src [0 ]; 1901params .src1 = * node -> src [1 ]; 1902params .dst = * node ; 1903params .dim = dim ; 1904 1905// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1906ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1907bool cpu_comparison_active = false; 1908if (concat_cpu_compare_config .enabled ) { 1909if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_CONCAT )) { 1910cpu_comparison_active = true; 1911 }else { 1912GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for CONCAT operation\n" ); 1913 } 1914 } 1915 1916bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1917 1918// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1919if (cpu_comparison_active ) { 1920if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& concat_cpu_compare_config )) { 1921GGML_LOG_WARN ("ET: CPU comparison failed for CONCAT operation\n" ); 1922 } 1923ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1924 } 1925 1926ET_PERF_END_EXT ("CONCAT" ,kernel_name ,node ,"dim=%d" ,dim ); 1927return kernel_result ; 1928} 1929 1930bool ggml_et_op_repeat (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1931ET_PERF_START (); 1932 1933if (!dev_ctx || !node ) { 1934GGML_LOG_ERROR ("ET: Invalid parameters for REPEAT operation\n" ); 1935return false; 1936 } 1937 1938if (!node -> src [0 ]) { 1939GGML_LOG_ERROR ("ET: REPEAT operation missing required input\n" ); 1940return false; 1941 } 1942 1943const char * kernel_name ; 1944 1945if (node -> type == GGML_TYPE_F32 && node -> src [0 ]-> type == GGML_TYPE_F32 ) { 1946// No-op REPEAT (every repeat factor is 1): the output is just a copy 1947// of the input. Route to cont_f32, whose contiguous fast path handles 1948// arbitrary sizes (including those rejected by repeat_f32's gate, 1949// e.g. ne[0]=1). 1950if (ggml_are_same_shape (node -> src [0 ],node )) { 1951kernel_name = "cont_f32" ; 1952 }else { 1953kernel_name = "repeat_f32" ; 1954 } 1955 1956 }else { 1957GGML_LOG_ERROR ("ET: REPEAT operation with unsupported types: dst=%s src0=%s\n" ,ggml_type_name (node -> type ), 1958ggml_type_name (node -> src [0 ]-> type )); 1959return false; 1960 } 1961 1962// ggml_et_cont_params and ggml_et_repeat_params have identical layouts 1963// (just src0 + dst), so the same payload works for either kernel. 1964ggml_et_repeat_params params ; 1965params .src0 = * node -> src [0 ]; 1966params .dst = * node ; 1967 1968// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 1969ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 1970bool cpu_comparison_active = false; 1971if (repeat_cpu_compare_config .enabled ) { 1972if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_REPEAT )) { 1973cpu_comparison_active = true; 1974 }else { 1975GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for REPEAT operation\n" ); 1976 } 1977 } 1978 1979bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 1980 1981// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 1982if (cpu_comparison_active ) { 1983if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& repeat_cpu_compare_config )) { 1984GGML_LOG_WARN ("ET: CPU comparison failed for REPEAT operation\n" ); 1985 } 1986ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 1987 } 1988 1989ET_PERF_END ("REPEAT" ,kernel_name ,node ); 1990return kernel_result ; 1991} 1992 1993bool ggml_et_op_ssm_conv (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 1994ET_PERF_START (); 1995 1996if (!dev_ctx || !node || !node -> src [0 ]|| !node -> src [1 ]) { 1997GGML_LOG_ERROR ("ET: Invalid parameters for SSM_CONV operation\n" ); 1998return false; 1999 } 2000 2001if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 || node -> src [1 ]-> type != GGML_TYPE_F32 ) { 2002GGML_LOG_ERROR ("ET: SSM_CONV operation with unsupported types: dst=%s src0=%s src1=%s\n" , 2003ggml_type_name (node -> type ),ggml_type_name (node -> src [0 ]-> type ), 2004ggml_type_name (node -> src [1 ]-> type )); 2005return false; 2006 } 2007 2008const char * kernel_name = "ssm_conv_f32" ; 2009 2010ggml_et_ssm_conv_params params ; 2011params .src0 = * node -> src [0 ]; 2012params .src1 = * node -> src [1 ]; 2013params .dst = * node ; 2014 2015ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 2016bool cpu_comparison_active = false; 2017if (ssm_conv_cpu_compare_config .enabled ) { 2018if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_SSM_CONV )) { 2019cpu_comparison_active = true; 2020 }else { 2021GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for SSM_CONV operation\n" ); 2022 } 2023 } 2024 2025bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 2026 2027if (cpu_comparison_active ) { 2028if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& ssm_conv_cpu_compare_config )) { 2029GGML_LOG_WARN ("ET: CPU comparison failed for SSM_CONV operation\n" ); 2030 } 2031ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 2032 } 2033 2034ET_PERF_END ("SSM_CONV" ,kernel_name ,node ); 2035return kernel_result ; 2036} 2037 2038bool ggml_et_op_ssm_scan (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2039ET_PERF_START (); 2040 2041if (!dev_ctx || !node ) { 2042GGML_LOG_ERROR ("ET: Invalid parameters for SSM_SCAN operation\n" ); 2043return false; 2044 } 2045 2046for (int i = 0 ;i < 7 ;++ i ) { 2047if (!node -> src [i ]) { 2048GGML_LOG_ERROR ("ET: SSM_SCAN missing required input %d\n" ,i ); 2049return false; 2050 } 2051 } 2052 2053if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 || node -> src [1 ]-> type != GGML_TYPE_F32 || 2054node -> src [2 ]-> type != GGML_TYPE_F32 || node -> src [3 ]-> type != GGML_TYPE_F32 || 2055node -> src [4 ]-> type != GGML_TYPE_F32 || node -> src [5 ]-> type != GGML_TYPE_F32 || 2056node -> src [6 ]-> type != GGML_TYPE_I32 ) { 2057GGML_LOG_ERROR ("ET: SSM_SCAN operation with unsupported types\n" ); 2058return false; 2059 } 2060 2061ggml_et_ssm_scan_params params ; 2062params .src0 = * node -> src [0 ]; 2063params .src1 = * node -> src [1 ]; 2064params .src2 = * node -> src [2 ]; 2065params .src3 = * node -> src [3 ]; 2066params .src4 = * node -> src [4 ]; 2067params .src5 = * node -> src [5 ]; 2068params .src6 = * node -> src [6 ]; 2069params .dst = * node ; 2070params .K = ggml_get_op_params_i32 (node ,0 ); 2071 2072bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"ssm_scan_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 2073 2074ET_PERF_END ("SSM_SCAN" ,"ssm_scan_f32" ,node ); 2075return kernel_result ; 2076} 2077 2078bool ggml_et_op_rwkv_wkv6 (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2079ET_PERF_START (); 2080 2081if (!dev_ctx || !node ) { 2082GGML_LOG_ERROR ("ET: Invalid parameters for RWKV_WKV6 operation\n" ); 2083return false; 2084 } 2085 2086// Validate all 6 source tensors exist 2087for (int i = 0 ;i <=5 ;i ++ ) { 2088if (!node -> src [i ]) { 2089GGML_LOG_ERROR ("ET: RWKV_WKV6 operation missing src[%d]\n" ,i ); 2090return false; 2091 } 2092 } 2093 2094if (node -> type != GGML_TYPE_F32 ) { 2095GGML_LOG_ERROR ("ET: RWKV_WKV6 only supports F32, got %s\n" ,ggml_type_name (node -> type )); 2096return false; 2097 } 2098 2099const char * kernel_name = "rwkv_wkv6_f32" ; 2100 2101const int64_t S = node -> src [0 ]-> ne [0 ];// head_size 2102const int64_t H = node -> src [0 ]-> ne [1 ];// num heads 2103const int64_t T = node -> src [1 ]-> ne [2 ];// num tokens 2104const int64_t n_seqs = node -> src [5 ]-> ne [1 ];// num sequences 2105const int64_t C = S * H ; 2106 2107ggml_et_rwkv_wkv6_params params ; 2108params .k = (float * )node -> src [0 ]-> data ; 2109params .v = (float * )node -> src [1 ]-> data ; 2110params .r = (float * )node -> src [2 ]-> data ; 2111params .tf = (float * )node -> src [3 ]-> data ; 2112params .td = (float * )node -> src [4 ]-> data ; 2113params .state_in = (float * )node -> src [5 ]-> data ; 2114params .dst = (float * )node -> data ; 2115params .C = (int32_t )C ; 2116params .H = (int32_t )H ; 2117params .S = (int32_t )S ; 2118params .T = (int32_t )T ; 2119params .n_seqs = (int32_t )n_seqs ; 2120 2121// Phase 1: Initialize CPU comparison context 2122ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 2123bool cpu_comparison_active = false; 2124if (rwkv_wkv6_cpu_compare_config .enabled ) { 2125if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_RWKV_WKV6 )) { 2126cpu_comparison_active = true; 2127 }else { 2128GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for RWKV_WKV6 operation\n" ); 2129 } 2130 } 2131 2132bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 2133 2134// Phase 2: Execute CPU computation and compare 2135if (cpu_comparison_active ) { 2136if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& rwkv_wkv6_cpu_compare_config )) { 2137GGML_LOG_WARN ("ET: CPU comparison failed for RWKV_WKV6 operation\n" ); 2138 } 2139ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 2140 } 2141 2142ET_PERF_END_EXT ("RWKV_WKV6" ,kernel_name ,node ,"S=%d H=%d T=%d n_seqs=%d" , (int )S , (int )H , (int )T , 2143 (int )n_seqs ); 2144return kernel_result ; 2145} 2146 2147bool ggml_et_op_rwkv_wkv7 (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2148ET_PERF_START (); 2149 2150if (!dev_ctx || !node ) { 2151GGML_LOG_ERROR ("ET: Invalid parameters for RWKV_WKV7 operation\n" ); 2152return false; 2153 } 2154 2155// Validate all 7 source tensors exist 2156for (int i = 0 ;i <=6 ;i ++ ) { 2157if (!node -> src [i ]) { 2158GGML_LOG_ERROR ("ET: RWKV_WKV7 operation missing src[%d]\n" ,i ); 2159return false; 2160 } 2161 } 2162 2163if (node -> type != GGML_TYPE_F32 ) { 2164GGML_LOG_ERROR ("ET: RWKV_WKV7 only supports F32, got %s\n" ,ggml_type_name (node -> type )); 2165return false; 2166 } 2167 2168const char * kernel_name = "rwkv_wkv7_f32" ; 2169 2170const int64_t S = node -> src [2 ]-> ne [0 ];// head_size 2171const int64_t H = node -> src [2 ]-> ne [1 ];// num heads 2172const int64_t T = node -> src [1 ]-> ne [2 ];// num tokens 2173const int64_t n_seqs = node -> src [6 ]-> ne [1 ];// num sequences 2174const int64_t C = S * H ; 2175 2176ggml_et_rwkv_wkv7_params params ; 2177params .r = (float * )node -> src [0 ]-> data ; 2178params .w = (float * )node -> src [1 ]-> data ; 2179params .k = (float * )node -> src [2 ]-> data ; 2180params .v = (float * )node -> src [3 ]-> data ; 2181params .a = (float * )node -> src [4 ]-> data ; 2182params .b = (float * )node -> src [5 ]-> data ; 2183params .state_in = (float * )node -> src [6 ]-> data ; 2184params .dst = (float * )node -> data ; 2185params .C = (int32_t )C ; 2186params .H = (int32_t )H ; 2187params .S = (int32_t )S ; 2188params .T = (int32_t )T ; 2189params .n_seqs = (int32_t )n_seqs ; 2190 2191// Phase 1: Initialize CPU comparison context 2192ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 2193bool cpu_comparison_active = false; 2194if (rwkv_wkv7_cpu_compare_config .enabled ) { 2195if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_RWKV_WKV7 )) { 2196cpu_comparison_active = true; 2197 }else { 2198GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for RWKV_WKV7 operation\n" ); 2199 } 2200 } 2201 2202bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 2203 2204// Phase 2: Execute CPU computation and compare 2205if (cpu_comparison_active ) { 2206if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& rwkv_wkv7_cpu_compare_config )) { 2207GGML_LOG_WARN ("ET: CPU comparison failed for RWKV_WKV7 operation\n" ); 2208 } 2209ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 2210 } 2211 2212ET_PERF_END_EXT ("RWKV_WKV7" ,kernel_name ,node ,"S=%d H=%d T=%d n_seqs=%d" , (int )S , (int )H , (int )T , 2213 (int )n_seqs ); 2214return kernel_result ; 2215} 2216 2217static ggml_et_cpu_compare_config gated_delta_net_cpu_compare_config = { 2218/* .enabled = */ false, 2219/* .use_cpu_result = */ false, 2220/* .log_differences = */ true, 2221/* .tolerance = */ 1e-4f , 2222/* .max_log_elements = */ 4096 2223}; 2224 2225bool ggml_et_op_gated_delta_net (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2226ET_PERF_START (); 2227 2228if (!dev_ctx || !node ) { 2229GGML_LOG_ERROR ("ET: Invalid parameters for GATED_DELTA_NET operation\n" ); 2230return false; 2231 } 2232 2233// Validate all 6 source tensors exist 2234for (int i = 0 ;i <=5 ;i ++ ) { 2235if (!node -> src [i ]) { 2236GGML_LOG_ERROR ("ET: GATED_DELTA_NET operation missing src[%d]\n" ,i ); 2237return false; 2238 } 2239 } 2240 2241if (node -> type != GGML_TYPE_F32 ) { 2242GGML_LOG_ERROR ("ET: GATED_DELTA_NET only supports F32, got %s\n" ,ggml_type_name (node -> type )); 2243return false; 2244 } 2245 2246const char * kernel_name = "gated_delta_net_f32" ; 2247 2248const ggml_tensor * src_q = node -> src [0 ]; 2249const ggml_tensor * src_k = node -> src [1 ]; 2250const ggml_tensor * src_v = node -> src [2 ]; 2251const ggml_tensor * src_g = node -> src [3 ]; 2252const ggml_tensor * src_beta = node -> src [4 ]; 2253const ggml_tensor * src_state = node -> src [5 ]; 2254 2255const int64_t S_v = src_v -> ne [0 ]; 2256const int64_t H = src_v -> ne [1 ]; 2257const int64_t n_tokens = src_v -> ne [2 ]; 2258const int64_t n_seqs = src_v -> ne [3 ]; 2259const int64_t H_q = src_q -> ne [1 ]; 2260const int64_t H_k = src_k -> ne [1 ]; 2261const int64_t n_seqs_q = src_q -> ne [3 ]; 2262const int64_t n_seqs_k = src_k -> ne [3 ]; 2263 2264ggml_et_gated_delta_net_params params ; 2265params .q = * src_q ; 2266params .k = * src_k ; 2267params .v = * src_v ; 2268params .g = * src_g ; 2269params .beta = * src_beta ; 2270params .state_in = * src_state ; 2271params .dst = * node ; 2272params .S_v = (int32_t )S_v ; 2273params .H = (int32_t )H ; 2274params .H_q = (int32_t )H_q ; 2275params .H_k = (int32_t )H_k ; 2276params .n_tokens = (int32_t )n_tokens ; 2277params .n_seqs = (int32_t )n_seqs ; 2278params .n_seqs_q = (int32_t )n_seqs_q ; 2279params .n_seqs_k = (int32_t )n_seqs_k ; 2280params .kda = (src_g -> ne [0 ]== S_v ) ?1 :0 ; 2281params .K = ggml_get_op_params_i32 (node ,0 ); 2282params .scale = 1.0f /sqrtf ((float )S_v ); 2283 2284// CPU comparison for debugging 2285ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 2286bool cpu_comparison_active = false; 2287if (gated_delta_net_cpu_compare_config .enabled ) { 2288if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_GATED_DELTA_NET )) { 2289cpu_comparison_active = true; 2290 }else { 2291GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for GATED_DELTA_NET operation\n" ); 2292 } 2293 } 2294 2295bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 2296 2297if (cpu_comparison_active ) { 2298if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& gated_delta_net_cpu_compare_config )) { 2299GGML_LOG_WARN ("ET: CPU comparison failed for GATED_DELTA_NET operation\n" ); 2300 } 2301ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 2302 } 2303 2304ET_PERF_END_EXT ("GATED_DELTA_NET" ,kernel_name ,node ,"S_v=%d H=%d n_tokens=%d n_seqs=%d kda=%d" , (int )S_v , 2305 (int )H , (int )n_tokens , (int )n_seqs ,params .kda ); 2306return kernel_result ; 2307} 2308 2309bool ggml_et_op_set_rows (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2310ET_PERF_START (); 2311 2312if (!dev_ctx || !node ) { 2313GGML_LOG_ERROR ("ET: Invalid parameters for SET_ROWS operation\n" ); 2314return false; 2315 } 2316 2317if (!node -> src [0 ]|| !node -> src [1 ]|| !node -> src [2 ]) { 2318GGML_LOG_ERROR ( 2319"ET: SET_ROWS operation missing required inputs (needs src[0]=base, src[1]=indices, src[2]=data)\n" ); 2320return false; 2321 } 2322 2323const char * kernel_name ; 2324 2325// Support F32 data with I64 indices -> F32/F16 output (scatter operation) 2326if (node -> src [0 ]-> type == GGML_TYPE_F32 && node -> src [1 ]-> type == GGML_TYPE_I64 && 2327 (node -> type == GGML_TYPE_F32 || node -> type == GGML_TYPE_F16 )) { 2328if (node -> type == GGML_TYPE_F32 || node -> type == GGML_TYPE_F16 ) { 2329kernel_name = "set_rows_f32" ; 2330 }else { 2331GGML_LOG_ERROR ("ET: SET_ROWS unsupported output type: %s\n" ,ggml_type_name (node -> type )); 2332return false; 2333 } 2334 2335 }else { 2336GGML_LOG_ERROR ("ET: SET_ROWS operation with unsupported types: dst=%s src0=%s src1=%s\n" , 2337ggml_type_name (node -> type ),ggml_type_name (node -> src [0 ]-> type ), 2338ggml_type_name (node -> src [1 ]-> type )); 2339return false; 2340 } 2341 2342// Validate contiguity requirements 2343if (!ggml_is_contiguous_rows (node )) { 2344GGML_LOG_ERROR ("ET: SET_ROWS operation requires contiguous-rows destination tensor\n" ); 2345return false; 2346 } 2347 2348if (!ggml_is_contiguous_rows (node -> src [0 ])) { 2349GGML_LOG_ERROR ("ET: SET_ROWS operation requires contiguous-rows source tensor\n" ); 2350return false; 2351 } 2352 2353if (!ggml_is_contiguous (node -> src [1 ])) { 2354GGML_LOG_ERROR ("ET: SET_ROWS operation requires contiguous indices tensor\n" ); 2355return false; 2356 } 2357 2358// Validate dimension constraints from ggml implementation 2359if (!(node -> ne [0 ]== node -> src [0 ]-> ne [0 ]&& // same number of columns 2360node -> ne [2 ]== node -> src [0 ]-> ne [2 ]&& // same batch size 2361node -> ne [3 ]== node -> src [0 ]-> ne [3 ]&& // same outer dimension 2362node -> src [0 ]-> ne [1 ]== node -> src [1 ]-> ne [0 ]&& // src rows = index count 2363node -> src [0 ]-> ne [2 ] %node -> src [1 ]-> ne [1 ]== 0 && // batch constraint 2364node -> src [0 ]-> ne [3 ] %node -> src [1 ]-> ne [2 ]== 0 && // outer constraint 2365node -> src [1 ]-> ne [3 ]== 1 )) {// indices constraint 2366GGML_LOG_ERROR ("ET: SET_ROWS operation dimension constraint failed\n" ); 2367return false; 2368 } 2369 2370ggml_et_set_rows_params params ; 2371params .src0 = * node -> src [0 ];// F32 source data tensor 2372params .src1 = * node -> src [1 ];// I64 indices tensor 2373params .dst = * node ;// F32/F16 destination tensor 2374 2375// Phase 1: Initialize CPU comparison context and copy source buffers (before ET kernel) 2376ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 2377bool cpu_comparison_active = false; 2378if (set_rows_cpu_compare_config .enabled ) { 2379if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_SET_ROWS )) { 2380cpu_comparison_active = true; 2381 }else { 2382GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for SET_ROWS operation\n" ); 2383 } 2384 } 2385 2386bool kernel_result = ggml_et_launch_kernel (dev_ctx ,kernel_name ,& params ,sizeof (params ),0xFFFFFFFF ); 2387 2388// Phase 2: Execute CPU computation and compare with ET result (after ET kernel) 2389if (cpu_comparison_active ) { 2390if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& set_rows_cpu_compare_config )) { 2391GGML_LOG_WARN ("ET: CPU comparison failed for SET_ROWS operation\n" ); 2392 } 2393ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 2394 } 2395 2396ET_PERF_END ("SET_ROWS" ,kernel_name ,node ); 2397return kernel_result ; 2398} 2399 2400bool ggml_et_op_fill (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2401ET_PERF_START (); 2402 2403ggml_et_fill_params params ; 2404params .dst = * node ; 2405memcpy (& params .c ,node -> op_params ,sizeof (float )); 2406 2407bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"fill_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 2408 2409ET_PERF_END ("FILL" ,"fill_f32" ,node ); 2410return kernel_result ; 2411} 2412 2413bool ggml_et_op_diag (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2414ET_PERF_START (); 2415 2416if (!node -> src [0 ]) { 2417GGML_LOG_ERROR ("ET: DIAG operation missing source tensor\n" ); 2418return false; 2419 } 2420 2421ggml_et_diag_params params ; 2422params .src0 = * node -> src [0 ]; 2423params .dst = * node ; 2424 2425bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"diag_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 2426 2427ET_PERF_END ("DIAG" ,"diag_f32" ,node ); 2428return kernel_result ; 2429} 2430 2431bool ggml_et_op_tri (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2432ET_PERF_START (); 2433 2434if (!node -> src [0 ]) { 2435GGML_LOG_ERROR ("ET: TRI operation missing source tensor\n" ); 2436return false; 2437 } 2438 2439ggml_et_tri_params params ; 2440params .src0 = * node -> src [0 ]; 2441params .dst = * node ; 2442memcpy (& params .tri_type ,node -> op_params ,sizeof (int32_t )); 2443 2444bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"tri_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 2445 2446ET_PERF_END ("TRI" ,"tri_f32" ,node ); 2447return kernel_result ; 2448} 2449 2450bool ggml_et_op_solve_tri (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2451ET_PERF_START (); 2452 2453if (!node -> src [0 ]|| !node -> src [1 ]) { 2454GGML_LOG_ERROR ("ET: SOLVE_TRI operation missing source tensor(s)\n" ); 2455return false; 2456 } 2457 2458ggml_et_solve_tri_params params ; 2459params .src0 = * node -> src [0 ];// A (lower-triangular) 2460params .src1 = * node -> src [1 ];// B (RHS) 2461params .dst = * node ;// X (solution) 2462 2463bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"solve_tri_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 2464 2465ET_PERF_END ("SOLVE_TRI" ,"solve_tri_f32" ,node ); 2466return kernel_result ; 2467} 2468 2469bool ggml_et_op_set (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2470ET_PERF_START (); 2471 2472if (!node -> src [0 ]|| !node -> src [1 ]) { 2473GGML_LOG_ERROR ("ET: SET operation missing source tensor(s)\n" ); 2474return false; 2475 } 2476 2477const bool inplace = (bool ) ((const int32_t * )node -> op_params )[4 ]; 2478const size_t offset = ((const int32_t * )node -> op_params )[3 ]; 2479const size_t nb1 = ((const int32_t * )node -> op_params )[0 ]; 2480const size_t nb2 = ((const int32_t * )node -> op_params )[1 ]; 2481const size_t nb3 = ((const int32_t * )node -> op_params )[2 ]; 2482 2483if (!inplace ) { 2484GGML_LOG_ERROR ("ET: SET only supports inplace (inplace=%d)\n" ,inplace ); 2485return false; 2486 } 2487 2488if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 || node -> src [1 ]-> type != GGML_TYPE_F32 ) { 2489GGML_LOG_ERROR ("ET: SET only supports F32 (dst=%s src0=%s src1=%s)\n" ,ggml_type_name (node -> type ), 2490ggml_type_name (node -> src [0 ]-> type ),ggml_type_name (node -> src [1 ]-> type )); 2491return false; 2492 } 2493 2494if (!ggml_are_same_shape (node ,node -> src [0 ])) { 2495GGML_LOG_ERROR ("ET: SET requires same-shape src0 and dst\n" ); 2496return false; 2497 } 2498 2499if (!ggml_is_contiguous (node )|| !ggml_is_contiguous (node -> src [0 ])|| !ggml_is_contiguous (node -> src [1 ])) { 2500GGML_LOG_ERROR ("ET: SET requires contiguous dst, src0, and src1\n" ); 2501return false; 2502 } 2503 2504ggml_et_set_params params ; 2505params .src1 = * node -> src [1 ]; 2506params .dst = * node ; 2507params .nb1 = (int32_t )nb1 ; 2508params .nb2 = (int32_t )nb2 ; 2509params .nb3 = (int32_t )nb3 ; 2510params .offset = (int32_t )offset ; 2511 2512bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"set_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 2513 2514ET_PERF_END ("SET" ,"set_f32" ,node ); 2515return kernel_result ; 2516} 2517 2518bool ggml_et_op_pad (ggml_backend_et_device_context * dev_ctx ,const ggml_tensor * node ) { 2519ET_PERF_START (); 2520 2521if (!node -> src [0 ]) { 2522GGML_LOG_ERROR ("ET: PAD operation missing source tensor\n" ); 2523return false; 2524 } 2525 2526if (node -> type != GGML_TYPE_F32 || node -> src [0 ]-> type != GGML_TYPE_F32 ) { 2527GGML_LOG_ERROR ("ET: PAD only supports F32 (src=%s dst=%s)\n" ,ggml_type_name (node -> src [0 ]-> type ), 2528ggml_type_name (node -> type )); 2529return false; 2530 } 2531 2532if (!ggml_is_contiguous (node )) { 2533GGML_LOG_ERROR ("ET: PAD requires contiguous output tensor\n" ); 2534return false; 2535 } 2536 2537if (node -> src [0 ]-> nb [0 ]!= sizeof (float )) { 2538GGML_LOG_ERROR ("ET: PAD requires element-contiguous src dim0 (nb[0]=%zu)\n" , (size_t )node -> src [0 ]-> nb [0 ]); 2539return false; 2540 } 2541 2542// Extract padding parameters from op_params 2543const int32_t * op_params = (const int32_t * )node -> op_params ; 2544 2545ggml_et_pad_params params ; 2546params .src0 = * node -> src [0 ]; 2547params .dst = * node ; 2548params .lp [0 ]= op_params [0 ]; 2549params .rp [0 ]= op_params [1 ]; 2550params .lp [1 ]= op_params [2 ]; 2551params .rp [1 ]= op_params [3 ]; 2552params .lp [2 ]= op_params [4 ]; 2553params .rp [2 ]= op_params [5 ]; 2554params .lp [3 ]= op_params [6 ]; 2555params .rp [3 ]= op_params [7 ]; 2556 2557// v1: no dim0 padding 2558if (params .lp [0 ]!= 0 || params .rp [0 ]!= 0 ) { 2559GGML_LOG_ERROR ("ET: PAD dim0 padding not supported (lp0=%d rp0=%d)\n" ,params .lp [0 ],params .rp [0 ]); 2560return false; 2561 } 2562 2563ggml_et_cpu_compare_ctx cpu_cmp_ctx ; 2564bool cpu_comparison_active = false; 2565if (pad_cpu_compare_config .enabled ) { 2566if (ggml_et_cpu_compare_init_pre (& cpu_cmp_ctx ,node ,GGML_OP_PAD )) { 2567cpu_comparison_active = true; 2568 }else { 2569GGML_LOG_WARN ("ET: Failed to initialize CPU comparison for PAD operation\n" ); 2570 } 2571 } 2572 2573bool kernel_result = ggml_et_launch_kernel (dev_ctx ,"pad_f32" ,& params ,sizeof (params ),0xFFFFFFFF ); 2574 2575if (cpu_comparison_active ) { 2576if (!ggml_et_cpu_compare_compute_and_check (& cpu_cmp_ctx ,node ,& pad_cpu_compare_config )) { 2577GGML_LOG_WARN ("ET: CPU comparison failed for PAD operation\n" ); 2578 } 2579ggml_et_cpu_compare_free (& cpu_cmp_ctx ); 2580 } 2581 2582ET_PERF_END ("PAD" ,"pad_f32" ,node ); 2583return kernel_result ; 2584}