char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
85c55223c
char/aliceai-t5-moe
1#define _CRT_SECURE_NO_DEPRECATE // Disables "unsafe" warnings on Windows 2#define _USE_MATH_DEFINES // For M_PI on MSVC 3 4#include "ggml-backend-impl.h" 5#include "ggml-backend.h" 6#include "traits.h" 7#include "iqp.h" 8#include "ggml-cpu-impl.h" 9#include "ggml-impl.h" 10#include "quants.h" 11#include "ggml-threading.h" 12#include "unary-ops.h" 13#include "binary-ops.h" 14#include "vec.h" 15#include "ops.h" 16#include "ggml.h" 17#include "common.h" 18 19#if defined(_MSC_VER )|| defined(__MINGW32__ ) 20#include <malloc.h> // using malloc.h with MSC/MINGW 21#elif !defined(__FreeBSD__ )&& !defined(__NetBSD__ )&& !defined(__OpenBSD__ ) 22#include <alloca.h> 23#endif 24 25#include <assert.h> 26#include <errno.h> 27#include <time.h> 28#include <math.h> 29#include <stdlib.h> 30#include <string.h> 31#include <stdint.h> 32#include <inttypes.h> 33#include <stdio.h> 34#include <float.h> 35#include <limits.h> 36#include <stdarg.h> 37#include <signal.h> 38#if defined(__gnu_linux__ ) 39#include <syscall.h> 40#endif 41 42#ifdef GGML_USE_OPENMP 43#include <omp.h> 44#endif 45 46#if defined(__ARM_FEATURE_SVE )|| defined(__ARM_FEATURE_MATMUL_INT8 ) 47#undef GGML_USE_LLAMAFILE 48#endif 49 50#ifdef GGML_USE_LLAMAFILE 51#include "llamafile/sgemm.h" 52#endif 53 54#ifdef GGML_USE_CPU_RISCV64_SPACEMIT 55# include "spacemit/ime.h" 56#endif 57 58// Note: once we move threading into a separate C++ file 59// will use std::hardware_destructive_interference_size instead of hardcoding it here 60// and we'll use C++ attribute syntax. 61#define GGML_CACHE_LINE 64 62 63#if defined(__clang__ )|| defined(__GNUC__ ) 64#define GGML_CACHE_ALIGN __attribute__((aligned(GGML_CACHE_LINE))) 65#endif 66 67#if defined(__has_feature ) 68#if __has_feature (thread_sanitizer ) 69#define GGML_TSAN_ENABLED 1 70#endif 71#else // __has_feature 72#if defined(__SANITIZE_THREAD__ ) 73#define GGML_TSAN_ENABLED 1 74#endif 75#endif // __has_feature 76 77#define UNUSED GGML_UNUSED 78#define SWAP (x ,y ,T ) do { T SWAP = x; (x) = y; (y) = SWAP; } while (0) 79 80// precomputed f32 table for f16 (256 KB) (simd-mappings.h) 81float ggml_table_f32_f16 [1 <<16 ]; 82 83// precomputed f32 table for e8m0 half (1 KB) (simd-mappings.h) 84float ggml_table_f32_e8m0_half [1 <<8 ]; 85 86// precomputed f32 table for ue4m3 (1 KB) (simd-mappings.h) 87float ggml_table_f32_ue4m3 [1 <<8 ]; 88 89#if defined(__ARM_ARCH ) 90struct ggml_arm_arch_features_type { 91int sve_cnt ; 92}ggml_arm_arch_features = {0 }; 93#endif 94 95#if defined(__riscv ) 96struct ggml_riscv_arch_features_type { 97int rvv_vlen ; 98}ggml_riscv_arch_features = {0 }; 99#endif 100 101#if defined(_WIN32 ) 102 103#define WIN32_LEAN_AND_MEAN 104#ifndef NOMINMAX 105#define NOMINMAX 106#endif 107#include <windows.h> 108 109#if defined(_MSC_VER )&& !defined(__clang__ ) 110#define GGML_CACHE_ALIGN __declspec(align(GGML_CACHE_LINE)) 111 112typedef volatile LONG atomic_int ; 113typedef atomic_int atomic_bool ; 114typedef atomic_int atomic_flag ; 115 116#define ATOMIC_FLAG_INIT 0 117 118typedef enum { 119memory_order_relaxed , 120memory_order_consume , 121memory_order_acquire , 122memory_order_release , 123memory_order_acq_rel , 124memory_order_seq_cst 125}memory_order ; 126 127static void atomic_store (atomic_int * ptr ,LONG val ) { 128InterlockedExchange (ptr ,val ); 129} 130static void atomic_store_explicit (atomic_int * ptr ,LONG val ,memory_order mo ) { 131// TODO: add support for explicit memory order 132InterlockedExchange (ptr ,val ); 133} 134static LONG atomic_load (atomic_int * ptr ) { 135return InterlockedCompareExchange (ptr ,0 ,0 ); 136} 137static LONG atomic_load_explicit (atomic_int * ptr ,memory_order mo ) { 138// TODO: add support for explicit memory order 139return InterlockedCompareExchange (ptr ,0 ,0 ); 140} 141static LONG atomic_fetch_add (atomic_int * ptr ,LONG inc ) { 142return InterlockedExchangeAdd (ptr ,inc ); 143} 144static LONG atomic_fetch_add_explicit (atomic_int * ptr ,LONG inc ,memory_order mo ) { 145// TODO: add support for explicit memory order 146return InterlockedExchangeAdd (ptr ,inc ); 147} 148static atomic_bool atomic_flag_test_and_set (atomic_flag * ptr ) { 149return InterlockedExchange (ptr ,1 ); 150} 151static void atomic_flag_clear (atomic_flag * ptr ) { 152InterlockedExchange (ptr ,0 ); 153} 154static void atomic_thread_fence (memory_order mo ) { 155MemoryBarrier (); 156} 157#else // clang 158#include <stdatomic.h> 159#endif 160 161typedef HANDLE pthread_t ; 162 163typedef DWORD thread_ret_t ; 164static int pthread_create (pthread_t * out ,void * unused ,thread_ret_t (* func )(void * ),void * arg ) { 165 (void )unused ; 166HANDLE handle = CreateThread (NULL ,0 , (LPTHREAD_START_ROUTINE )func ,arg ,0 ,NULL ); 167if (handle == NULL ) 168 { 169return EAGAIN ; 170 } 171 172* out = handle ; 173return 0 ; 174} 175 176static int pthread_join (pthread_t thread ,void * unused ) { 177 (void )unused ; 178int ret = (int )WaitForSingleObject (thread ,INFINITE ); 179CloseHandle (thread ); 180return ret ; 181} 182 183static int sched_yield (void ) { 184Sleep (0 ); 185return 0 ; 186} 187#else 188 189#include <pthread.h> 190#include <stdatomic.h> 191#include <sched.h> 192#if defined(__FreeBSD__ ) 193#include <pthread_np.h> 194#endif 195 196typedef void * thread_ret_t ; 197 198#include <sys/types.h> 199#include <sys/stat.h> 200#include <unistd.h> 201 202#endif 203 204typedef pthread_t ggml_thread_t ; 205 206#define GGML_THREADPOOL_N_THREADS_MASK (0xffffU) 207#define GGML_THREADPOOL_N_THREADS_BITS (16) 208 209#if defined(__APPLE__ ) 210#include <unistd.h> 211#include <mach/mach.h> 212#include <TargetConditionals.h> 213#endif 214 215static const struct ggml_type_traits_cpu type_traits_cpu [GGML_TYPE_COUNT ]= { 216 [GGML_TYPE_F32 ]= { 217 .from_float = (ggml_from_float_t )ggml_cpu_fp32_to_fp32 , 218 .vec_dot = (ggml_vec_dot_t )ggml_vec_dot_f32 , 219 .vec_dot_type = GGML_TYPE_F32 , 220 .nrows = 1 , 221 }, 222 [GGML_TYPE_F16 ]= { 223 .from_float = (ggml_from_float_t )ggml_cpu_fp32_to_fp16 , 224 .vec_dot = (ggml_vec_dot_t )ggml_vec_dot_f16 , 225 .vec_dot_type = GGML_TYPE_F16 , 226 .nrows = 1 , 227 }, 228 [GGML_TYPE_Q1_0 ]= { 229 .from_float = quantize_row_q1_0 , 230 .vec_dot = ggml_vec_dot_q1_0_q8_0 , 231 .vec_dot_type = GGML_TYPE_Q8_0 , 232 .nrows = 1 , 233 }, 234 [GGML_TYPE_Q2_0 ]= { 235 .from_float = quantize_row_q2_0 , 236 .vec_dot = ggml_vec_dot_q2_0_q8_0 , 237 .vec_dot_type = GGML_TYPE_Q8_0 , 238 .nrows = 1 , 239 }, 240 [GGML_TYPE_Q4_0 ]= { 241 .from_float = quantize_row_q4_0 , 242 .vec_dot = ggml_vec_dot_q4_0_q8_0 , 243 .vec_dot_type = GGML_TYPE_Q8_0 , 244#if defined (__ARM_FEATURE_MATMUL_INT8 ) 245 .nrows = 2 , 246#else 247 .nrows = 1 , 248#endif 249 }, 250 [GGML_TYPE_Q4_1 ]= { 251 .from_float = quantize_row_q4_1 , 252 .vec_dot = ggml_vec_dot_q4_1_q8_1 , 253 .vec_dot_type = GGML_TYPE_Q8_1 , 254#if defined (__ARM_FEATURE_MATMUL_INT8 ) 255 .nrows = 2 , 256#else 257 .nrows = 1 , 258#endif 259 }, 260 [GGML_TYPE_Q5_0 ]= { 261 .from_float = quantize_row_q5_0 , 262 .vec_dot = ggml_vec_dot_q5_0_q8_0 , 263 .vec_dot_type = GGML_TYPE_Q8_0 , 264 .nrows = 1 , 265 }, 266 [GGML_TYPE_Q5_1 ]= { 267 .from_float = quantize_row_q5_1 , 268 .vec_dot = ggml_vec_dot_q5_1_q8_1 , 269 .vec_dot_type = GGML_TYPE_Q8_1 , 270 .nrows = 1 , 271 }, 272 [GGML_TYPE_Q8_0 ]= { 273 .from_float = quantize_row_q8_0 , 274 .vec_dot = ggml_vec_dot_q8_0_q8_0 , 275 .vec_dot_type = GGML_TYPE_Q8_0 , 276#if defined (__ARM_FEATURE_MATMUL_INT8 ) 277 .nrows = 2 , 278#else 279 .nrows = 1 , 280#endif 281 }, 282 [GGML_TYPE_Q8_1 ]= { 283 .from_float = quantize_row_q8_1 , 284 .vec_dot_type = GGML_TYPE_Q8_1 , 285 .nrows = 1 , 286 }, 287 [GGML_TYPE_MXFP4 ]= { 288 .from_float = quantize_row_mxfp4 , 289 .vec_dot = ggml_vec_dot_mxfp4_q8_0 , 290 .vec_dot_type = GGML_TYPE_Q8_0 , 291 .nrows = 1 , 292 }, 293 [GGML_TYPE_NVFP4 ]= { 294 .from_float = quantize_row_nvfp4 , 295 .vec_dot = ggml_vec_dot_nvfp4_q8_0 , 296 .vec_dot_type = GGML_TYPE_Q8_0 , 297 .nrows = 1 , 298 }, 299 [GGML_TYPE_Q2_K ]= { 300 .from_float = quantize_row_q2_K , 301 .vec_dot = ggml_vec_dot_q2_K_q8_K , 302 .vec_dot_type = GGML_TYPE_Q8_K , 303 .nrows = 1 , 304 }, 305 [GGML_TYPE_Q3_K ]= { 306 .from_float = quantize_row_q3_K , 307 .vec_dot = ggml_vec_dot_q3_K_q8_K , 308 .vec_dot_type = GGML_TYPE_Q8_K , 309 .nrows = 1 , 310 }, 311 [GGML_TYPE_Q4_K ]= { 312 .from_float = quantize_row_q4_K , 313 .vec_dot = ggml_vec_dot_q4_K_q8_K , 314 .vec_dot_type = GGML_TYPE_Q8_K , 315#if defined (__ARM_FEATURE_MATMUL_INT8 ) 316 .nrows = 2 , 317#else 318 .nrows = 1 , 319#endif 320 }, 321 [GGML_TYPE_Q5_K ]= { 322 .from_float = quantize_row_q5_K , 323 .vec_dot = ggml_vec_dot_q5_K_q8_K , 324 .vec_dot_type = GGML_TYPE_Q8_K , 325 .nrows = 1 , 326 }, 327 [GGML_TYPE_Q6_K ]= { 328 .from_float = quantize_row_q6_K , 329 .vec_dot = ggml_vec_dot_q6_K_q8_K , 330 .vec_dot_type = GGML_TYPE_Q8_K , 331#if defined (__ARM_FEATURE_MATMUL_INT8 ) 332 .nrows = 2 , 333#else 334 .nrows = 1 , 335#endif 336 }, 337 [GGML_TYPE_IQ2_XXS ]= { 338 .from_float = NULL , 339 .vec_dot = ggml_vec_dot_iq2_xxs_q8_K , 340 .vec_dot_type = GGML_TYPE_Q8_K , 341 .nrows = 1 , 342 }, 343 [GGML_TYPE_IQ2_XS ]= { 344 .from_float = NULL , 345 .vec_dot = ggml_vec_dot_iq2_xs_q8_K , 346 .vec_dot_type = GGML_TYPE_Q8_K , 347 .nrows = 1 , 348 }, 349 [GGML_TYPE_IQ3_XXS ]= { 350// NOTE: from_float for iq3 and iq2_s was removed because these quants require initialization in ggml_quantize_init 351//.from_float = quantize_row_iq3_xxs, 352 .vec_dot = ggml_vec_dot_iq3_xxs_q8_K , 353 .vec_dot_type = GGML_TYPE_Q8_K , 354 .nrows = 1 , 355 }, 356 [GGML_TYPE_IQ3_S ]= { 357//.from_float = quantize_row_iq3_s, 358 .vec_dot = ggml_vec_dot_iq3_s_q8_K , 359 .vec_dot_type = GGML_TYPE_Q8_K , 360 .nrows = 1 , 361 }, 362 [GGML_TYPE_IQ2_S ]= { 363//.from_float = quantize_row_iq2_s, 364 .vec_dot = ggml_vec_dot_iq2_s_q8_K , 365 .vec_dot_type = GGML_TYPE_Q8_K , 366 .nrows = 1 , 367 }, 368 [GGML_TYPE_IQ1_S ]= { 369 .from_float = NULL , 370 .vec_dot = ggml_vec_dot_iq1_s_q8_K , 371 .vec_dot_type = GGML_TYPE_Q8_K , 372 .nrows = 1 , 373 }, 374 [GGML_TYPE_IQ1_M ]= { 375 .from_float = NULL , 376 .vec_dot = ggml_vec_dot_iq1_m_q8_K , 377 .vec_dot_type = GGML_TYPE_Q8_K , 378 .nrows = 1 , 379 }, 380 [GGML_TYPE_IQ4_NL ]= { 381 .from_float = quantize_row_iq4_nl , 382 .vec_dot = ggml_vec_dot_iq4_nl_q8_0 , 383 .vec_dot_type = GGML_TYPE_Q8_0 , 384 .nrows = 1 , 385 }, 386 [GGML_TYPE_IQ4_XS ]= { 387 .from_float = quantize_row_iq4_xs , 388 .vec_dot = ggml_vec_dot_iq4_xs_q8_K , 389 .vec_dot_type = GGML_TYPE_Q8_K , 390 .nrows = 1 , 391 }, 392 [GGML_TYPE_Q8_K ]= { 393 .from_float = quantize_row_q8_K , 394 }, 395 [GGML_TYPE_BF16 ]= { 396 .from_float = (ggml_from_float_t )ggml_cpu_fp32_to_bf16 , 397 .vec_dot = (ggml_vec_dot_t )ggml_vec_dot_bf16 , 398 .vec_dot_type = GGML_TYPE_BF16 , 399 .nrows = 1 , 400 }, 401 [GGML_TYPE_TQ1_0 ]= { 402 .from_float = quantize_row_tq1_0 , 403 .vec_dot = ggml_vec_dot_tq1_0_q8_K , 404 .vec_dot_type = GGML_TYPE_Q8_K , 405 .nrows = 1 , 406 }, 407 [GGML_TYPE_TQ2_0 ]= { 408 .from_float = quantize_row_tq2_0 , 409 .vec_dot = ggml_vec_dot_tq2_0_q8_K , 410 .vec_dot_type = GGML_TYPE_Q8_K , 411 .nrows = 1 , 412 }, 413 [GGML_TYPE_I32 ]= { 414 .from_float = (ggml_from_float_t )ggml_cpu_fp32_to_i32 , 415 }, 416}; 417 418const struct ggml_type_traits_cpu * ggml_get_type_traits_cpu (enum ggml_type type ) { 419return & type_traits_cpu [type ]; 420} 421 422// 423// Threading defs 424// 425 426typedef pthread_t ggml_thread_t ; 427 428#if defined(_WIN32 ) 429 430typedef CONDITION_VARIABLE ggml_cond_t ; 431typedef SRWLOCK ggml_mutex_t ; 432 433#define ggml_mutex_init (m ) InitializeSRWLock(m) 434#define ggml_mutex_destroy (m ) 435#define ggml_mutex_lock (m ) AcquireSRWLockExclusive(m) 436#define ggml_mutex_unlock (m ) ReleaseSRWLockExclusive(m) 437#define ggml_mutex_lock_shared (m ) AcquireSRWLockShared(m) 438#define ggml_mutex_unlock_shared (m ) ReleaseSRWLockShared(m) 439 440#define ggml_cond_init (c ) InitializeConditionVariable(c) 441#define ggml_cond_destroy (c ) 442#define ggml_cond_wait (c ,m ) SleepConditionVariableSRW(c, m, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED) 443#define ggml_cond_broadcast (c ) WakeAllConditionVariable(c) 444 445#define ggml_thread_create pthread_create 446#define ggml_thread_join pthread_join 447 448#else 449 450typedef pthread_cond_t ggml_cond_t ; 451typedef pthread_mutex_t ggml_mutex_t ; 452 453#define ggml_mutex_init (m ) pthread_mutex_init(m, NULL) 454#define ggml_mutex_destroy (m ) pthread_mutex_destroy(m) 455#define ggml_mutex_lock (m ) pthread_mutex_lock(m) 456#define ggml_mutex_unlock (m ) pthread_mutex_unlock(m) 457#define ggml_mutex_lock_shared (m ) pthread_mutex_lock(m) 458#define ggml_mutex_unlock_shared (m ) pthread_mutex_unlock(m) 459 460#define ggml_lock_init (x ) UNUSED(x) 461#define ggml_lock_destroy (x ) UNUSED(x) 462#if defined(__x86_64__ )|| (defined(_MSC_VER )&& defined(_M_AMD64 )) 463#define ggml_lock_lock (x ) _mm_pause() 464#else 465#define ggml_lock_lock (x ) UNUSED(x) 466#endif 467#define ggml_lock_unlock (x ) UNUSED(x) 468 469#define GGML_LOCK_INITIALIZER 0 470#define ggml_cond_init (c ) pthread_cond_init(c, NULL) 471#define ggml_cond_destroy (c ) pthread_cond_destroy(c) 472#define ggml_cond_wait (c ,m ) pthread_cond_wait(c, m) 473#define ggml_cond_broadcast (c ) pthread_cond_broadcast(c) 474 475#define ggml_thread_create pthread_create 476#define ggml_thread_join pthread_join 477 478#endif 479 480// Threadpool def 481struct ggml_threadpool { 482ggml_mutex_t mutex ;// mutex for cond.var 483ggml_cond_t cond ;// cond.var for waiting for new work 484 485struct ggml_cgraph * cgraph ; 486struct ggml_cplan * cplan ; 487 488// synchronization primitives 489atomic_int n_graph ;// updated when there is work to be done (i.e each graph) holds graph and active thread counts. 490atomic_int GGML_CACHE_ALIGN n_barrier ; 491atomic_int GGML_CACHE_ALIGN n_barrier_passed ; 492atomic_int GGML_CACHE_ALIGN current_chunk ;// currently processing chunk during Mat_Mul, shared between all the threads. 493 494// these are atomic as an annotation for thread-sanitizer 495atomic_bool stop ;// Used for stopping the threadpool altogether 496atomic_bool pause ;// Used for pausing the threadpool or individual threads 497atomic_int abort ;// Used for aborting processing of a graph 498 499struct ggml_compute_state * workers ;// per thread state 500int n_threads ;// Number of threads in the pool 501int32_t prio ;// Scheduling priority 502uint32_t poll ;// Polling level (0 - no polling) 503 504enum ggml_status ec ; 505}; 506 507// Per-thread state 508struct ggml_compute_state { 509#ifndef GGML_USE_OPENMP 510ggml_thread_t thrd ; 511int last_graph ; 512bool pending ; 513#endif 514bool cpumask [GGML_MAX_N_THREADS ]; 515struct ggml_threadpool * threadpool ; 516int ith ; 517}; 518 519// Helpers for polling loops 520#if defined(__aarch64__ )&& ( defined(__clang__ )|| defined(__GNUC__ ) ) 521static inline void ggml_thread_cpu_relax (void ) { 522 __asm__volatile ("yield" :::"memory" ); 523} 524#elif defined(__x86_64__ ) 525static inline void ggml_thread_cpu_relax (void ) { 526_mm_pause (); 527} 528#elif defined(__riscv ) 529static inline void ggml_thread_cpu_relax (void ) { 530#ifdef __riscv_zihintpause 531 __asm__ __volatile__ ("pause" ); 532#else 533/* Encoding of the pause instruction */ 534 __asm__ __volatile__ (".4byte 0x100000F" ); 535#endif 536} 537#else 538static inline void ggml_thread_cpu_relax (void ) {;} 539#endif 540 541// 542// NUMA support 543// 544 545#define GGML_NUMA_MAX_NODES 8 546#define GGML_NUMA_MAX_CPUS 512 547 548struct ggml_numa_node { 549uint32_t cpus [GGML_NUMA_MAX_CPUS ];// hardware threads on this node 550uint32_t n_cpus ; 551}; 552 553struct ggml_numa_nodes { 554enum ggml_numa_strategy numa_strategy ; 555struct ggml_numa_node nodes [GGML_NUMA_MAX_NODES ]; 556uint32_t n_nodes ; 557uint32_t total_cpus ;// hardware threads on system 558uint32_t current_node ;// node on which main process is execting 559#if defined(__gnu_linux__ ) 560cpu_set_t cpuset ;// cpuset from numactl 561#else 562uint32_t cpuset ;// no NUMA support outside of Linux at this time. Use a portable datatype 563#endif 564}; 565 566// 567// ggml state 568// 569 570struct ggml_state { 571struct ggml_numa_nodes numa ; 572}; 573 574static struct ggml_state g_state = {0 }; 575 576void ggml_barrier (struct ggml_threadpool * tp ) { 577int n_threads = atomic_load_explicit (& tp -> n_graph ,memory_order_relaxed )& GGML_THREADPOOL_N_THREADS_MASK ; 578if (n_threads == 1 ) { 579return ; 580 } 581 582#ifdef GGML_USE_OPENMP 583#pragma omp barrier 584#else 585int n_passed = atomic_load_explicit (& tp -> n_barrier_passed ,memory_order_relaxed ); 586 587// enter barrier (full seq-cst fence) 588int n_barrier = atomic_fetch_add_explicit (& tp -> n_barrier ,1 ,memory_order_seq_cst ); 589 590if (n_barrier == (n_threads - 1 )) { 591// last thread 592atomic_store_explicit (& tp -> n_barrier ,0 ,memory_order_relaxed ); 593 594// exit barrier (full seq-cst fence) 595atomic_fetch_add_explicit (& tp -> n_barrier_passed ,1 ,memory_order_seq_cst ); 596return ; 597 } 598 599// wait for other threads 600while (atomic_load_explicit (& tp -> n_barrier_passed ,memory_order_relaxed )== n_passed ) { 601ggml_thread_cpu_relax (); 602 } 603 604// exit barrier (full seq-cst fence) 605// TSAN doesn't support standalone fence yet, we use a dummy read-modify-write instead 606#ifdef GGML_TSAN_ENABLED 607atomic_fetch_add_explicit (& tp -> n_barrier_passed ,0 ,memory_order_seq_cst ); 608#else 609atomic_thread_fence (memory_order_seq_cst ); 610#endif 611#endif 612} 613 614void ggml_threadpool_chunk_set (struct ggml_threadpool * tp ,int value ) { 615atomic_store_explicit (& tp -> current_chunk ,value ,memory_order_relaxed ); 616} 617 618int ggml_threadpool_chunk_add (struct ggml_threadpool * tp ,int value ) { 619return atomic_fetch_add_explicit (& tp -> current_chunk ,value ,memory_order_relaxed ); 620} 621 622#if defined(__gnu_linux__ ) 623static cpu_set_t ggml_get_numa_affinity (void ) { 624cpu_set_t cpuset ; 625pthread_t thread ; 626thread = pthread_self (); 627CPU_ZERO (& cpuset ); 628pthread_getaffinity_np (thread ,sizeof (cpu_set_t ),& cpuset ); 629return cpuset ; 630} 631#else 632static uint32_t ggml_get_numa_affinity (void ) { 633return 0 ;// no NUMA support 634} 635#endif 636 637void ggml_numa_init (enum ggml_numa_strategy numa_flag ) { 638if (g_state .numa .n_nodes > 0 ) { 639fprintf (stderr ,"ggml_numa_init: NUMA already initialized\n" ); 640 641return ; 642 } 643 644#if defined(__gnu_linux__ ) 645struct stat st ; 646char path [256 ]; 647int rv ; 648 649// set numa scheme 650g_state .numa .numa_strategy = numa_flag ; 651 652GGML_PRINT_DEBUG ("numa strategy %u\n" ,g_state .numa .numa_strategy ); 653 654g_state .numa .cpuset = ggml_get_numa_affinity (); 655 656// enumerate nodes 657while (g_state .numa .n_nodes < GGML_NUMA_MAX_NODES ) { 658rv = snprintf (path ,sizeof (path ),"/sys/devices/system/node/node%u" ,g_state .numa .n_nodes ); 659GGML_ASSERT (rv > 0 && (unsigned )rv < sizeof (path )); 660if (stat (path ,& st )!= 0 ) {break ; } 661++ g_state .numa .n_nodes ; 662 } 663 664// enumerate CPUs 665while (g_state .numa .total_cpus < GGML_NUMA_MAX_CPUS ) { 666rv = snprintf (path ,sizeof (path ),"/sys/devices/system/cpu/cpu%u" ,g_state .numa .total_cpus ); 667GGML_ASSERT (rv > 0 && (unsigned )rv < sizeof (path )); 668if (stat (path ,& st )!= 0 ) {break ; } 669++ g_state .numa .total_cpus ; 670 } 671 672GGML_PRINT_DEBUG ("found %u numa nodes, %u CPUs\n" ,g_state .numa .n_nodes ,g_state .numa .total_cpus ); 673 674// figure out which node we're on 675uint current_cpu ; 676int getcpu_ret = 0 ; 677#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 33 )|| defined(__COSMOPOLITAN__ ) 678getcpu_ret = getcpu (& current_cpu ,& g_state .numa .current_node ); 679#else 680// old glibc doesn't have a wrapper for this call. Fall back on direct syscall 681# if !defined(SYS_getcpu )&& defined(SYS_get_cpu ) 682# define SYS_getcpu SYS_get_cpu // some older glibc versions use this name 683# endif 684getcpu_ret = syscall (SYS_getcpu ,& current_cpu ,& g_state .numa .current_node ); 685#endif 686 687if (g_state .numa .n_nodes < 1 || g_state .numa .total_cpus < 1 || getcpu_ret != 0 ) { 688g_state .numa .n_nodes = 0 ; 689return ; 690 } 691 692GGML_PRINT_DEBUG ("found our process on numa node %u, CPU %u\n" ,g_state .numa .current_node ,current_cpu ); 693 694for (uint32_t n = 0 ;n < g_state .numa .n_nodes ;++ n ) { 695struct ggml_numa_node * node = & g_state .numa .nodes [n ]; 696GGML_PRINT_DEBUG ("CPUs on node %u:" ,n ); 697node -> n_cpus = 0 ; 698for (uint32_t c = 0 ;c < g_state .numa .total_cpus ;++ c ) { 699rv = snprintf (path ,sizeof (path ),"/sys/devices/system/node/node%u/cpu%u" ,n ,c ); 700GGML_ASSERT (rv > 0 && (unsigned )rv < sizeof (path )); 701if (stat (path ,& st )== 0 ) { 702node -> cpus [node -> n_cpus ++ ]= c ; 703GGML_PRINT_DEBUG (" %u" ,c ); 704 } 705 } 706GGML_PRINT_DEBUG ("\n" ); 707 } 708 709if (ggml_is_numa ()) { 710FILE * fptr = fopen ("/proc/sys/kernel/numa_balancing" ,"r" ); 711if (fptr != NULL ) { 712char buf [42 ]; 713if (fgets (buf ,sizeof (buf ),fptr )&& strncmp (buf ,"0\n" ,sizeof (buf ))!= 0 ) { 714GGML_LOG_WARN ("/proc/sys/kernel/numa_balancing is enabled, this has been observed to impair performance\n" ); 715 } 716fclose (fptr ); 717 } 718 } 719#else 720UNUSED (numa_flag ); 721// TODO 722#endif 723} 724 725bool ggml_is_numa (void ) { 726return g_state .numa .n_nodes > 1 ; 727} 728 729#if defined(__ARM_ARCH ) 730#if defined(__aarch64__ )&& defined(__ARM_FEATURE_SVE ) 731#include <arm_sve.h> 732static void ggml_init_arm_arch_features (void ) { 733ggml_arm_arch_features .sve_cnt = svcntb (); 734} 735#else 736static void ggml_init_arm_arch_features (void ) {} 737#endif 738#endif // __ARM_ARCH 739 740#if defined(__riscv )&& defined(__riscv_v_intrinsic ) 741#include <riscv_vector.h> 742static void ggml_init_riscv_arch_features (void ) { 743ggml_riscv_arch_features .rvv_vlen = __riscv_vlenb (); 744} 745#else 746static void ggml_init_riscv_arch_features (void ) {} 747#endif 748 749struct ggml_tensor * ggml_new_i32 (struct ggml_context * ctx ,int32_t value ) { 750GGML_ASSERT (!ggml_get_no_alloc (ctx )); 751 752struct ggml_tensor * result = ggml_new_tensor_1d (ctx ,GGML_TYPE_I32 ,1 ); 753 754ggml_set_i32 (result ,value ); 755 756return result ; 757} 758 759struct ggml_tensor * ggml_new_f32 (struct ggml_context * ctx ,float value ) { 760GGML_ASSERT (!ggml_get_no_alloc (ctx )); 761 762struct ggml_tensor * result = ggml_new_tensor_1d (ctx ,GGML_TYPE_F32 ,1 ); 763 764ggml_set_f32 (result ,value ); 765 766return result ; 767} 768 769struct ggml_tensor * ggml_set_i32 (struct ggml_tensor * tensor ,int32_t value ) { 770const int n = ggml_nrows (tensor ); 771const int nc = tensor -> ne [0 ]; 772const size_t n1 = tensor -> nb [1 ]; 773 774char * const data = tensor -> data ; 775 776switch (tensor -> type ) { 777case GGML_TYPE_I8 : 778 { 779assert (tensor -> nb [0 ]== sizeof (int8_t )); 780for (int i = 0 ;i < n ;i ++ ) { 781ggml_vec_set_i8 (nc , (int8_t * )(data + i * n1 ),value ); 782 } 783 }break ; 784case GGML_TYPE_I16 : 785 { 786assert (tensor -> nb [0 ]== sizeof (int16_t )); 787for (int i = 0 ;i < n ;i ++ ) { 788ggml_vec_set_i16 (nc , (int16_t * )(data + i * n1 ),value ); 789 } 790 }break ; 791case GGML_TYPE_I32 : 792 { 793assert (tensor -> nb [0 ]== sizeof (int32_t )); 794for (int i = 0 ;i < n ;i ++ ) { 795ggml_vec_set_i32 (nc , (int32_t * )(data + i * n1 ),value ); 796 } 797 }break ; 798case GGML_TYPE_F16 : 799 { 800assert (tensor -> nb [0 ]== sizeof (ggml_fp16_t )); 801for (int i = 0 ;i < n ;i ++ ) { 802ggml_vec_set_f16 (nc , (ggml_fp16_t * )(data + i * n1 ),GGML_CPU_FP32_TO_FP16 (value )); 803 } 804 }break ; 805case GGML_TYPE_BF16 : 806 { 807assert (tensor -> nb [0 ]== sizeof (ggml_fp16_t )); 808for (int i = 0 ;i < n ;i ++ ) { 809ggml_vec_set_bf16 (nc , (ggml_bf16_t * )(data + i * n1 ),GGML_FP32_TO_BF16 (value )); 810 } 811 }break ; 812case GGML_TYPE_F32 : 813 { 814assert (tensor -> nb [0 ]== sizeof (float )); 815for (int i = 0 ;i < n ;i ++ ) { 816ggml_vec_set_f32 (nc , (float * )(data + i * n1 ),value ); 817 } 818 }break ; 819default : 820 { 821GGML_ABORT ("fatal error" ); 822 } 823 } 824 825return tensor ; 826} 827 828struct ggml_tensor * ggml_set_f32 (struct ggml_tensor * tensor ,float value ) { 829const int n = ggml_nrows (tensor ); 830const int nc = tensor -> ne [0 ]; 831const size_t n1 = tensor -> nb [1 ]; 832 833char * const data = tensor -> data ; 834 835switch (tensor -> type ) { 836case GGML_TYPE_I8 : 837 { 838assert (tensor -> nb [0 ]== sizeof (int8_t )); 839for (int i = 0 ;i < n ;i ++ ) { 840ggml_vec_set_i8 (nc , (int8_t * )(data + i * n1 ),value ); 841 } 842 }break ; 843case GGML_TYPE_I16 : 844 { 845assert (tensor -> nb [0 ]== sizeof (int16_t )); 846for (int i = 0 ;i < n ;i ++ ) { 847ggml_vec_set_i16 (nc , (int16_t * )(data + i * n1 ),value ); 848 } 849 }break ; 850case GGML_TYPE_I32 : 851 { 852assert (tensor -> nb [0 ]== sizeof (int32_t )); 853for (int i = 0 ;i < n ;i ++ ) { 854ggml_vec_set_i32 (nc , (int32_t * )(data + i * n1 ),value ); 855 } 856 }break ; 857case GGML_TYPE_F16 : 858 { 859assert (tensor -> nb [0 ]== sizeof (ggml_fp16_t )); 860for (int i = 0 ;i < n ;i ++ ) { 861ggml_vec_set_f16 (nc , (ggml_fp16_t * )(data + i * n1 ),GGML_CPU_FP32_TO_FP16 (value )); 862 } 863 }break ; 864case GGML_TYPE_BF16 : 865 { 866assert (tensor -> nb [0 ]== sizeof (ggml_bf16_t )); 867for (int i = 0 ;i < n ;i ++ ) { 868ggml_vec_set_bf16 (nc , (ggml_bf16_t * )(data + i * n1 ),GGML_FP32_TO_BF16 (value )); 869 } 870 }break ; 871case GGML_TYPE_F32 : 872 { 873assert (tensor -> nb [0 ]== sizeof (float )); 874for (int i = 0 ;i < n ;i ++ ) { 875ggml_vec_set_f32 (nc , (float * )(data + i * n1 ),value ); 876 } 877 }break ; 878default : 879 { 880GGML_ABORT ("fatal error" ); 881 } 882 } 883 884return tensor ; 885} 886 887int32_t ggml_get_i32_1d (const struct ggml_tensor * tensor ,int i ) { 888if (!ggml_is_contiguous (tensor )) { 889int64_t id [4 ]= {0 ,0 ,0 ,0 }; 890ggml_unravel_index (tensor ,i ,& id [0 ],& id [1 ],& id [2 ],& id [3 ]); 891return ggml_get_i32_nd (tensor ,id [0 ],id [1 ],id [2 ],id [3 ]); 892 } 893switch (tensor -> type ) { 894case GGML_TYPE_I8 : 895 { 896GGML_ASSERT (tensor -> nb [0 ]== sizeof (int8_t )); 897return ((int8_t * )(tensor -> data ))[i ]; 898 } 899case GGML_TYPE_I16 : 900 { 901GGML_ASSERT (tensor -> nb [0 ]== sizeof (int16_t )); 902return ((int16_t * )(tensor -> data ))[i ]; 903 } 904case GGML_TYPE_I32 : 905 { 906GGML_ASSERT (tensor -> nb [0 ]== sizeof (int32_t )); 907return ((int32_t * )(tensor -> data ))[i ]; 908 } 909case GGML_TYPE_F16 : 910 { 911GGML_ASSERT (tensor -> nb [0 ]== sizeof (ggml_fp16_t )); 912return GGML_CPU_FP16_TO_FP32 (((ggml_fp16_t * )(tensor -> data ))[i ]); 913 } 914case GGML_TYPE_BF16 : 915 { 916GGML_ASSERT (tensor -> nb [0 ]== sizeof (ggml_bf16_t )); 917return GGML_BF16_TO_FP32 (((ggml_bf16_t * )(tensor -> data ))[i ]); 918 } 919case GGML_TYPE_F32 : 920 { 921GGML_ASSERT (tensor -> nb [0 ]== sizeof (float )); 922return ((float * )(tensor -> data ))[i ]; 923 } 924default : 925 { 926GGML_ABORT ("fatal error" ); 927 } 928 } 929} 930 931void ggml_set_i32_1d (const struct ggml_tensor * tensor ,int i ,int32_t value ) { 932if (!ggml_is_contiguous (tensor )) { 933int64_t id [4 ]= {0 ,0 ,0 ,0 }; 934ggml_unravel_index (tensor ,i ,& id [0 ],& id [1 ],& id [2 ],& id [3 ]); 935ggml_set_i32_nd (tensor ,id [0 ],id [1 ],id [2 ],id [3 ],value ); 936return ; 937 } 938switch (tensor -> type ) { 939case GGML_TYPE_I8 : 940 { 941GGML_ASSERT (tensor -> nb [0 ]== sizeof (int8_t )); 942 ((int8_t * )(tensor -> data ))[i ]= value ; 943 }break ; 944case GGML_TYPE_I16 : 945 { 946GGML_ASSERT (tensor -> nb [0 ]== sizeof (int16_t )); 947 ((int16_t * )(tensor -> data ))[i ]= value ; 948 }break ; 949case GGML_TYPE_I32 : 950 { 951GGML_ASSERT (tensor -> nb [0 ]== sizeof (int32_t )); 952 ((int32_t * )(tensor -> data ))[i ]= value ; 953 }break ; 954case GGML_TYPE_F16 : 955 { 956GGML_ASSERT (tensor -> nb [0 ]== sizeof (ggml_fp16_t )); 957 ((ggml_fp16_t * )(tensor -> data ))[i ]= GGML_CPU_FP32_TO_FP16 (value ); 958 }break ; 959case GGML_TYPE_BF16 : 960 { 961GGML_ASSERT (tensor -> nb [0 ]== sizeof (ggml_bf16_t )); 962 ((ggml_bf16_t * )(tensor -> data ))[i ]= GGML_FP32_TO_BF16 (value ); 963 }break ; 964case GGML_TYPE_F32 : 965 { 966GGML_ASSERT (tensor -> nb [0 ]== sizeof (float )); 967 ((float * )(tensor -> data ))[i ]= value ; 968 }break ; 969default : 970 { 971GGML_ABORT ("fatal error" ); 972 } 973 } 974} 975 976int32_t ggml_get_i32_nd (const struct ggml_tensor * tensor ,int i0 ,int i1 ,int i2 ,int i3 ) { 977void * data = (char * )tensor -> data + i0 * tensor -> nb [0 ]+ i1 * tensor -> nb [1 ]+ i2 * tensor -> nb [2 ]+ i3 * tensor -> nb [3 ]; 978switch (tensor -> type ) { 979case GGML_TYPE_I8 : 980return ((int8_t * )data )[0 ]; 981case GGML_TYPE_I16 : 982return ((int16_t * )data )[0 ]; 983case GGML_TYPE_I32 : 984return ((int32_t * )data )[0 ]; 985case GGML_TYPE_F16 : 986return GGML_CPU_FP16_TO_FP32 (((ggml_fp16_t * )data )[0 ]); 987case GGML_TYPE_BF16 : 988return GGML_BF16_TO_FP32 (((ggml_bf16_t * )data )[0 ]); 989case GGML_TYPE_F32 : 990return ((float * )data )[0 ]; 991default : 992GGML_ABORT ("fatal error" ); 993 } 994} 995 996void ggml_set_i32_nd (const struct ggml_tensor * tensor ,int i0 ,int i1 ,int i2 ,int i3 ,int32_t value ) { 997void * data = (char * )tensor -> data + i0 * tensor -> nb [0 ]+ i1 * tensor -> nb [1 ]+ i2 * tensor -> nb [2 ]+ i3 * tensor -> nb [3 ]; 998switch (tensor -> type ) { 999case GGML_TYPE_I8 : 1000 { 1001 ((int8_t * )(data ))[0 ]= value ; 1002 }break ; 1003case GGML_TYPE_I16 : 1004 { 1005 ((int16_t * )(data ))[0 ]= value ; 1006 }break ; 1007case GGML_TYPE_I32 : 1008 { 1009 ((int32_t * )(data ))[0 ]= value ; 1010 }break ; 1011case GGML_TYPE_F16 : 1012 { 1013 ((ggml_fp16_t * )(data ))[0 ]= GGML_CPU_FP32_TO_FP16 (value ); 1014 }break ; 1015case GGML_TYPE_BF16 : 1016 { 1017 ((ggml_bf16_t * )(data ))[0 ]= GGML_FP32_TO_BF16 (value ); 1018 }break ; 1019case GGML_TYPE_F32 : 1020 { 1021 ((float * )(data ))[0 ]= value ; 1022 }break ; 1023default : 1024 { 1025GGML_ABORT ("fatal error" ); 1026 } 1027 } 1028} 1029 1030float ggml_get_f32_1d (const struct ggml_tensor * tensor ,int i ) { 1031if (!ggml_is_contiguous (tensor )) { 1032int64_t id [4 ]= {0 ,0 ,0 ,0 }; 1033ggml_unravel_index (tensor ,i ,& id [0 ],& id [1 ],& id [2 ],& id [3 ]); 1034return ggml_get_f32_nd (tensor ,id [0 ],id [1 ],id [2 ],id [3 ]); 1035 } 1036switch (tensor -> type ) { 1037case GGML_TYPE_I8 : 1038 { 1039return ((int8_t * )(tensor -> data ))[i ]; 1040 } 1041case GGML_TYPE_I16 : 1042 { 1043return ((int16_t * )(tensor -> data ))[i ]; 1044 } 1045case GGML_TYPE_I32 : 1046 { 1047return ((int32_t * )(tensor -> data ))[i ]; 1048 } 1049case GGML_TYPE_F16 : 1050 { 1051return GGML_CPU_FP16_TO_FP32 (((ggml_fp16_t * )(tensor -> data ))[i ]); 1052 } 1053case GGML_TYPE_BF16 : 1054 { 1055return GGML_BF16_TO_FP32 (((ggml_bf16_t * )(tensor -> data ))[i ]); 1056 } 1057case GGML_TYPE_F32 : 1058 { 1059return ((float * )(tensor -> data ))[i ]; 1060 } 1061default : 1062 { 1063GGML_ABORT ("fatal error" ); 1064 } 1065 } 1066} 1067 1068void ggml_set_f32_1d (const struct ggml_tensor * tensor ,int i ,float value ) { 1069if (!ggml_is_contiguous (tensor )) { 1070int64_t id [4 ]= {0 ,0 ,0 ,0 }; 1071ggml_unravel_index (tensor ,i ,& id [0 ],& id [1 ],& id [2 ],& id [3 ]); 1072ggml_set_f32_nd (tensor ,id [0 ],id [1 ],id [2 ],id [3 ],value ); 1073return ; 1074 } 1075switch (tensor -> type ) { 1076case GGML_TYPE_I8 : 1077 { 1078 ((int8_t * )(tensor -> data ))[i ]= value ; 1079 }break ; 1080case GGML_TYPE_I16 : 1081 { 1082 ((int16_t * )(tensor -> data ))[i ]= value ; 1083 }break ; 1084case GGML_TYPE_I32 : 1085 { 1086 ((int32_t * )(tensor -> data ))[i ]= value ; 1087 }break ; 1088case GGML_TYPE_F16 : 1089 { 1090 ((ggml_fp16_t * )(tensor -> data ))[i ]= GGML_CPU_FP32_TO_FP16 (value ); 1091 }break ; 1092case GGML_TYPE_BF16 : 1093 { 1094 ((ggml_bf16_t * )(tensor -> data ))[i ]= GGML_FP32_TO_BF16 (value ); 1095 }break ; 1096case GGML_TYPE_F32 : 1097 { 1098 ((float * )(tensor -> data ))[i ]= value ; 1099 }break ; 1100default : 1101 { 1102GGML_ABORT ("fatal error" ); 1103 } 1104 } 1105} 1106 1107float ggml_get_f32_nd (const struct ggml_tensor * tensor ,int i0 ,int i1 ,int i2 ,int i3 ) { 1108void * data = (char * )tensor -> data + i0 * tensor -> nb [0 ]+ i1 * tensor -> nb [1 ]+ i2 * tensor -> nb [2 ]+ i3 * tensor -> nb [3 ]; 1109switch (tensor -> type ) { 1110case GGML_TYPE_I8 : 1111return ((int8_t * )data )[0 ]; 1112case GGML_TYPE_I16 : 1113return ((int16_t * )data )[0 ]; 1114case GGML_TYPE_I32 : 1115return ((int32_t * )data )[0 ]; 1116case GGML_TYPE_F16 : 1117return GGML_CPU_FP16_TO_FP32 (((ggml_fp16_t * )data )[0 ]); 1118case GGML_TYPE_BF16 : 1119return GGML_BF16_TO_FP32 (((ggml_bf16_t * )data )[0 ]); 1120case GGML_TYPE_F32 : 1121return ((float * )data )[0 ]; 1122default : 1123GGML_ABORT ("fatal error" ); 1124 } 1125} 1126 1127void ggml_set_f32_nd (const struct ggml_tensor * tensor ,int i0 ,int i1 ,int i2 ,int i3 ,float value ) { 1128void * data = (char * )tensor -> data + i0 * tensor -> nb [0 ]+ i1 * tensor -> nb [1 ]+ i2 * tensor -> nb [2 ]+ i3 * tensor -> nb [3 ]; 1129switch (tensor -> type ) { 1130case GGML_TYPE_I8 : 1131 { 1132 ((int8_t * )(data ))[0 ]= value ; 1133 }break ; 1134case GGML_TYPE_I16 : 1135 { 1136 ((int16_t * )(data ))[0 ]= value ; 1137 }break ; 1138case GGML_TYPE_I32 : 1139 { 1140 ((int32_t * )(data ))[0 ]= value ; 1141 }break ; 1142case GGML_TYPE_F16 : 1143 { 1144 ((ggml_fp16_t * )(data ))[0 ]= GGML_CPU_FP32_TO_FP16 (value ); 1145 }break ; 1146case GGML_TYPE_BF16 : 1147 { 1148 ((ggml_bf16_t * )(data ))[0 ]= GGML_FP32_TO_BF16 (value ); 1149 }break ; 1150case GGML_TYPE_F32 : 1151 { 1152 ((float * )(data ))[0 ]= value ; 1153 }break ; 1154default : 1155 { 1156GGML_ABORT ("fatal error" ); 1157 } 1158 } 1159} 1160 1161//////////////////////////////////////////////////////////////////////////////// 1162 1163// ggml_compute_forward_mul_mat 1164 1165static void ggml_compute_forward_mul_mat_one_chunk ( 1166const struct ggml_compute_params * params , 1167struct ggml_tensor * dst , 1168const enum ggml_type type , 1169const int64_t num_rows_per_vec_dot , 1170const int64_t ir0_start , 1171const int64_t ir0_end , 1172const int64_t ir1_start , 1173const int64_t ir1_end ) { 1174 1175const struct ggml_tensor * src0 = dst -> src [0 ]; 1176const struct ggml_tensor * src1 = dst -> src [1 ]; 1177 1178GGML_TENSOR_BINARY_OP_LOCALS 1179 1180const bool src1_cont = ggml_is_contiguous (src1 ); 1181 1182ggml_vec_dot_t const vec_dot = type_traits_cpu [type ].vec_dot ; 1183enum ggml_type const vec_dot_type = type_traits_cpu [type ].vec_dot_type ; 1184 1185// broadcast factors 1186const int64_t r2 = ne12 /ne02 ; 1187const int64_t r3 = ne13 /ne03 ; 1188 1189//printf("ir0_start = %6lld, ir0_end = %6lld, ir1_start = %6lld, ir1_end = %6lld\n", ir0_start, ir0_end, ir1_start, ir1_end); 1190 1191// threads with no work simply yield (not sure if it helps) 1192if (ir0_start >=ir0_end || ir1_start >=ir1_end ) { 1193return ; 1194 } 1195 1196const void * wdata = (src1 -> type == vec_dot_type ) ?src1 -> data :params -> wdata ; 1197const size_t row_size = ggml_row_size (vec_dot_type ,ne10 ); 1198 1199assert (ne12 %ne02 == 0 ); 1200assert (ne13 %ne03 == 0 ); 1201 1202// block-tiling attempt 1203const int64_t blck_0 = 16 ; 1204const int64_t blck_1 = 16 ; 1205 1206const size_t src1_col_stride = src1_cont || src1 -> type != vec_dot_type ?row_size :nb11 ; 1207 1208// attempt to reduce false-sharing (does not seem to make a difference) 1209// 16 * 2, accounting for mmla kernels 1210float tmp [32 ]; 1211 1212for (int64_t iir1 = ir1_start ;iir1 < ir1_end ;iir1 += blck_1 ) { 1213for (int64_t iir0 = ir0_start ;iir0 < ir0_end ;iir0 += blck_0 ) { 1214for (int64_t ir1 = iir1 ;ir1 < iir1 + blck_1 && ir1 < ir1_end ;ir1 += num_rows_per_vec_dot ) { 1215const int64_t i13 = (ir1 / (ne12 * ne1 )); 1216const int64_t i12 = (ir1 - i13 * ne12 * ne1 ) /ne1 ; 1217const int64_t i11 = (ir1 - i13 * ne12 * ne1 - i12 * ne1 ); 1218 1219// broadcast src0 into src1 1220const int64_t i03 = i13 /r3 ; 1221const int64_t i02 = i12 /r2 ; 1222 1223const int64_t i1 = i11 ; 1224const int64_t i2 = i12 ; 1225const int64_t i3 = i13 ; 1226 1227const char * src0_row = (const char * )src0 -> data + (0 + i02 * nb02 + i03 * nb03 ); 1228 1229// desc: when src1 is not a contiguous memory block we have to calculate the offset using the strides 1230// if it is, then we have either copied the data to params->wdata and made it contiguous or we are using 1231// the original src1 data pointer, so we should index using the indices directly 1232// TODO: this is a bit of a hack, we should probably have a better way to handle this 1233const char * src1_col = (const char * )wdata + 1234 (src1_cont || src1 -> type != vec_dot_type 1235 ? (i11 + i12 * ne11 + i13 * ne12 * ne11 )* row_size 1236 : (i11 * nb11 + i12 * nb12 + i13 * nb13 )); 1237float * dst_col = (float * )((char * )dst -> data + (i1 * nb1 + i2 * nb2 + i3 * nb3 )); 1238 1239//for (int64_t ir0 = iir0; ir0 < iir0 + blck_0 && ir0 < ir0_end; ++ir0) { 1240// vec_dot(ne00, &dst_col[ir0], src0_row + ir0*nb01, src1_col); 1241//} 1242 1243for (int64_t ir0 = iir0 ;ir0 < iir0 + blck_0 && ir0 < ir0_end ;ir0 += num_rows_per_vec_dot ) { 1244vec_dot (ne00 ,& tmp [ir0 - iir0 ], (num_rows_per_vec_dot > 1 ?16 :0 ),src0_row + ir0 * nb01 , (num_rows_per_vec_dot > 1 ?nb01 :0 ),src1_col , (num_rows_per_vec_dot > 1 ?src1_col_stride :0 ),num_rows_per_vec_dot ); 1245 } 1246 1247for (int cn = 0 ;cn < num_rows_per_vec_dot ;++ cn ) { 1248memcpy (& dst_col [iir0 + cn * nb1 /nb0 ],tmp + (cn * 16 ), (MIN (iir0 + blck_0 ,ir0_end )- iir0 )* sizeof (float )); 1249 } 1250 } 1251 } 1252 } 1253} 1254 1255void ggml_compute_forward_mul_mat ( 1256const struct ggml_compute_params * params , 1257struct ggml_tensor * dst ) { 1258 1259const struct ggml_tensor * src0 = dst -> src [0 ]; 1260const struct ggml_tensor * src1 = dst -> src [1 ]; 1261 1262const int32_t hint = ggml_get_op_params_i32 (dst ,1 ); 1263if (hint == GGML_HINT_SRC0_IS_HADAMARD && !params -> use_ref ) { 1264ggml_compute_forward_fwht (params ,dst ); 1265return ; 1266 } 1267 1268GGML_TENSOR_BINARY_OP_LOCALS 1269 1270const int ith = params -> ith ; 1271const int nth = params -> nth ; 1272 1273enum ggml_type const vec_dot_type = type_traits_cpu [src0 -> type ].vec_dot_type ; 1274ggml_from_float_t const from_float = type_traits_cpu [vec_dot_type ].from_float ; 1275int64_t const vec_dot_num_rows = type_traits_cpu [src0 -> type ].nrows ; 1276 1277GGML_ASSERT (ne0 == ne01 ); 1278GGML_ASSERT (ne1 == ne11 ); 1279GGML_ASSERT (ne2 == ne12 ); 1280GGML_ASSERT (ne3 == ne13 ); 1281 1282// we don't support permuted src0 or src1 1283GGML_ASSERT (nb00 == ggml_type_size (src0 -> type )); 1284GGML_ASSERT (nb10 == ggml_type_size (src1 -> type )); 1285 1286// dst cannot be transposed or permuted 1287GGML_ASSERT (nb0 == sizeof (float )); 1288GGML_ASSERT (nb0 <=nb1 ); 1289GGML_ASSERT (nb1 <=nb2 ); 1290GGML_ASSERT (nb2 <=nb3 ); 1291 1292// nb01 >= nb00 - src0 is not transposed 1293// compute by src0 rows 1294 1295// TODO: extract to "extra_op" 1296#if GGML_USE_LLAMAFILE 1297// broadcast factors 1298const int64_t r2 = ne12 /ne02 ; 1299const int64_t r3 = ne13 /ne03 ; 1300 1301const bool src1_cont = ggml_is_contiguous (src1 ); 1302 1303if (src1_cont ) { 1304for (int64_t i13 = 0 ;i13 < ne13 ;i13 ++ ) 1305for (int64_t i12 = 0 ;i12 < ne12 ;i12 ++ ) 1306if (!llamafile_sgemm (params , 1307ne01 ,ne11 ,ne00 /ggml_blck_size (src0 -> type ), 1308 (const char * )src0 -> data + i12 /r2 * nb02 + i13 /r3 * nb03 , 1309nb01 /ggml_type_size (src0 -> type ), 1310 (const char * )src1 -> data + i12 * nb12 + i13 * nb13 , 1311nb11 /ggml_type_size (src1 -> type ), 1312 (char * )dst -> data + i12 * nb2 + i13 * nb3 , 1313nb1 /ggml_type_size (dst -> type ), 1314src0 -> type , 1315src1 -> type , 1316dst -> type )) 1317 gotoUseGgmlGemm1 ; 1318return ; 1319 } 1320UseGgmlGemm1 :; 1321#endif 1322 1323if (src1 -> type != vec_dot_type ) { 1324char * wdata = params -> wdata ; 1325 1326const size_t nbw0 = ggml_type_size (vec_dot_type ); 1327const size_t nbw1 = ggml_row_size (vec_dot_type ,ne10 ); 1328const size_t nbw2 = nbw1 * ne11 ; 1329const size_t nbw3 = nbw2 * ne12 ; 1330 1331assert (params -> wsize >=ne13 * nbw3 ); 1332GGML_ASSERT (src1 -> type == GGML_TYPE_F32 ); 1333 1334#if 0 1335for (int64_t i13 = 0 ;i13 < ne13 ;++ i13 ) { 1336for (int64_t i12 = 0 ;i12 < ne12 ;++ i12 ) { 1337for (int64_t i11 = ith ;i11 < ne11 ;i11 += nth ) { 1338from_float ((float * )((char * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 ), 1339 (void * ) (wdata + i13 * nbw3 + i12 * nbw2 + i11 * nbw1 ), 1340ne10 ); 1341 } 1342 } 1343 } 1344#else 1345for (int64_t i13 = 0 ;i13 < ne13 ;++ i13 ) { 1346for (int64_t i12 = 0 ;i12 < ne12 ;++ i12 ) { 1347for (int64_t i11 = 0 ;i11 < ne11 ;++ i11 ) { 1348size_t bs = ggml_blck_size (vec_dot_type ); 1349int64_t ne10_block_start = (ith * ne10 /bs ) /nth ; 1350int64_t ne10_block_end = ((ith + 1 )* ne10 /bs ) /nth ; 1351from_float ((float * )((char * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 + ne10_block_start * bs * nb10 ), 1352 (void * ) (wdata + i13 * nbw3 + i12 * nbw2 + i11 * nbw1 + ne10_block_start * nbw0 ), 1353 (ne10_block_end - ne10_block_start )* bs ); 1354 } 1355 } 1356 } 1357#endif 1358 } 1359 1360if (ith == 0 ) { 1361// Every thread starts at ith, so the first unprocessed chunk is nth. This save a bit of coordination right at the start. 1362atomic_store_explicit (& params -> threadpool -> current_chunk ,nth ,memory_order_relaxed ); 1363 } 1364 1365ggml_barrier (params -> threadpool ); 1366 1367// IQ panel gemm (see iqp.h) - must come after the barrier above, it consumes the q8_K rows 1368// of src1 from the work buffer 1369if (ggml_cpu_iqp_supports_mul_mat (dst )&& !params -> use_ref ) { 1370ggml_compute_forward_mul_mat_iqp (params ,dst ); 1371return ; 1372 } 1373 1374#if GGML_USE_LLAMAFILE 1375if (src1 -> type != vec_dot_type ) { 1376const void * wdata = (src1 -> type == vec_dot_type ) ?src1 -> data :params -> wdata ; 1377const size_t row_size = ggml_row_size (vec_dot_type ,ne10 ); 1378 1379for (int64_t i13 = 0 ;i13 < ne13 ;i13 ++ ) 1380for (int64_t i12 = 0 ;i12 < ne12 ;i12 ++ ) 1381if (!llamafile_sgemm (params , 1382ne01 ,ne11 ,ne00 /ggml_blck_size (src0 -> type ), 1383 (const char * )src0 -> data + i12 /r2 * nb02 + i13 /r3 * nb03 , 1384nb01 /ggml_type_size (src0 -> type ), 1385 (const char * )wdata + (i12 * ne11 + i13 * ne12 * ne11 )* row_size , 1386row_size /ggml_type_size (vec_dot_type ), 1387 (char * )dst -> data + i12 * nb2 + i13 * nb3 , 1388nb1 /ggml_type_size (dst -> type ), 1389src0 -> type , 1390vec_dot_type , 1391dst -> type )) 1392 gotoUseGgmlGemm2 ; 1393return ; 1394 } 1395UseGgmlGemm2 :; 1396#endif 1397 1398// This is the size of the first dimension of the result, so we can iterate that way. (see the ASSERT above, these are the same numbers) 1399const int64_t nr0 = ne0 ; 1400 1401// This is the size of the rest of the dimensions of the result 1402const int64_t nr1 = ne1 * ne2 * ne3 ; 1403 1404// Now select a reasonable chunk size. 1405int chunk_size = 16 ; 1406 1407// We need to step up the size if it's small 1408if (nr0 == 1 || nr1 == 1 ) { 1409chunk_size = 64 ; 1410 } 1411 1412// distribute the work across the inner or outer loop based on which one is larger 1413// The number of chunks in the 0/1 dim. 1414// CEIL(nr0/chunk_size) 1415int64_t nchunk0 = (nr0 + chunk_size - 1 ) /chunk_size ; 1416int64_t nchunk1 = (nr1 + chunk_size - 1 ) /chunk_size ; 1417 1418// If the chunking is poor for the number of threads on this setup, scrap the whole plan. Re-chunk it by thread. 1419// Also, chunking by thread was measured to have perform better on NUMA systems. See https://github.com/ggml-org/llama.cpp/pull/6915 1420// In theory, chunking should be just as useful on NUMA and non NUMA systems, but testing disagreed with that. 1421if (nchunk0 * nchunk1 < nth * 4 || ggml_is_numa ()) { 1422// distribute the thread work across the inner or outer loop based on which one is larger 1423nchunk0 = nr0 > nr1 ?nth :1 ;// parallelize by src0 rows 1424nchunk1 = nr0 > nr1 ?1 :nth ;// parallelize by src1 rows 1425 } 1426 1427// The number of elements in each chunk 1428const int64_t dr0 = (nr0 + nchunk0 - 1 ) /nchunk0 ; 1429const int64_t dr1 = (nr1 + nchunk1 - 1 ) /nchunk1 ; 1430 1431// The first chunk comes from our thread_id, the rest will get auto-assigned. 1432int current_chunk = ith ; 1433 1434while (current_chunk < nchunk0 * nchunk1 ) { 1435const int64_t ith0 = current_chunk %nchunk0 ; 1436const int64_t ith1 = current_chunk /nchunk0 ; 1437 1438const int64_t ir0_start = dr0 * ith0 ; 1439const int64_t ir0_end = MIN (ir0_start + dr0 ,nr0 ); 1440 1441const int64_t ir1_start = dr1 * ith1 ; 1442const int64_t ir1_end = MIN (ir1_start + dr1 ,nr1 ); 1443 1444// dot kernels can handle 1 row and col at a time, but mmla kernels can process 2 rows and cols 1445int64_t num_rows_per_vec_dot = vec_dot_num_rows ; 1446 1447// these checks are needed to avoid crossing dim1 boundaries 1448// can be optimized, but the logic would become more complicated, so keeping it like this for simplicity 1449if ((nr0 %2 != 0 )|| (ne11 %2 != 0 )|| ((ir0_end - ir0_start ) %2 != 0 )|| ((ir1_end - ir1_start ) %2 != 0 )) { 1450num_rows_per_vec_dot = 1 ; 1451 } 1452ggml_compute_forward_mul_mat_one_chunk (params ,dst ,src0 -> type ,num_rows_per_vec_dot ,ir0_start ,ir0_end ,ir1_start ,ir1_end ); 1453 1454if (nth >=nchunk0 * nchunk1 ) { 1455break ; 1456 } 1457 1458current_chunk = atomic_fetch_add_explicit (& params -> threadpool -> current_chunk ,1 ,memory_order_relaxed ); 1459 } 1460} 1461 1462// ggml_compute_forward_mul_mat_id 1463 1464#define MMID_MATRIX_ROW (row_id ,i1 ) matrix_rows[(row_id)*ids->ne[0]*ids->ne[1] + (i1)] 1465 1466struct mmid_row_mapping { 1467int32_t i1 ; 1468int32_t i2 ; 1469}; 1470 1471static void ggml_compute_forward_mul_mat_id_one_chunk ( 1472struct ggml_tensor * dst , 1473const struct ggml_tensor * src0 , 1474const struct ggml_tensor * src1 , 1475const struct ggml_tensor * ids , 1476const int64_t cur_a , 1477const int64_t ir0_start , 1478const int64_t ir0_end , 1479const int64_t ir1_start , 1480const int64_t ir1_end , 1481const char * src0_cur , 1482const struct mmid_row_mapping * matrix_rows , 1483const size_t row_size , 1484const bool src1_cont , 1485const void * wdata ) { 1486 1487GGML_TENSOR_BINARY_OP_LOCALS 1488 1489const enum ggml_type type = src0 -> type ; 1490 1491ggml_vec_dot_t const vec_dot = type_traits_cpu [type ].vec_dot ; 1492enum ggml_type const vec_dot_type = type_traits_cpu [type ].vec_dot_type ; 1493 1494const int64_t blck_0 = 16 ; 1495const int64_t blck_1 = 16 ; 1496 1497float tmp [16 ]; 1498 1499for (int64_t iir1 = ir1_start ;iir1 < ir1_end ;iir1 += blck_1 ) { 1500for (int64_t iir0 = ir0_start ;iir0 < ir0_end ;iir0 += blck_0 ) { 1501for (int64_t ir1 = iir1 ;ir1 < iir1 + blck_1 && ir1 < ir1_end ;++ ir1 ) { 1502const int64_t _i12 = ir1 ;// logical row index for this expert 1503 1504struct mmid_row_mapping row_mapping = MMID_MATRIX_ROW (cur_a ,_i12 ); 1505const int id = row_mapping .i1 ;// selected expert index 1506 1507const int64_t i11 = id %ne11 ; 1508const int64_t i12 = row_mapping .i2 ;// row index in src1 1509 1510const int64_t i1 = id ;// selected expert index 1511const int64_t i2 = i12 ;// row 1512 1513// desc: when src1 is not a contiguous memory block we have to calculate the offset using the strides 1514// if it is, then we have either copied the data to params->wdata and made it contiguous or we are using 1515// the original src1 data pointer, so we should index using the indices directly 1516// TODO: this is a bit of a hack, we should probably have a better way to handle this 1517const char * src1_col = (const char * )wdata + 1518 (src1_cont || src1 -> type != vec_dot_type 1519 ? (i11 + i12 * ne11 )* row_size 1520 : (i11 * nb11 + i12 * nb12 )); 1521 1522float * dst_col = (float * ) ((char * )dst -> data + (i1 * nb1 + i2 * nb2 )); 1523 1524for (int64_t ir0 = iir0 ;ir0 < iir0 + blck_0 && ir0 < ir0_end ;++ ir0 ) { 1525vec_dot (ne00 ,& tmp [ir0 - iir0 ],0 ,src0_cur + ir0 * nb01 ,0 ,src1_col ,0 ,1 ); 1526 } 1527 1528memcpy (& dst_col [iir0 ],tmp , (MIN (iir0 + blck_0 ,ir0_end )- iir0 )* sizeof (float )); 1529 } 1530 } 1531 } 1532} 1533 1534static void * incr_ptr_aligned (void ** p ,size_t size ,size_t align ) { 1535 1536void * ptr = * p ; 1537ptr = (void * )GGML_PAD ((uintptr_t )ptr ,align ); 1538* p = (void * ) ((char * )ptr + size ); 1539return ptr ; 1540} 1541 1542static void ggml_compute_forward_mul_mat_id ( 1543const struct ggml_compute_params * params , 1544struct ggml_tensor * dst ) { 1545 1546const struct ggml_tensor * src0 = dst -> src [0 ]; 1547const struct ggml_tensor * src1 = dst -> src [1 ]; 1548const struct ggml_tensor * ids = dst -> src [2 ]; 1549 1550GGML_TENSOR_BINARY_OP_LOCALS 1551 1552const int ith = params -> ith ; 1553const int nth = params -> nth ; 1554 1555const enum ggml_type type = src0 -> type ; 1556 1557const bool src1_cont = ggml_is_contiguous (src1 ); 1558 1559enum ggml_type const vec_dot_type = type_traits_cpu [type ].vec_dot_type ; 1560ggml_from_float_t const from_float = type_traits_cpu [vec_dot_type ].from_float ; 1561 1562// we don't support permuted src0 or src1 1563GGML_ASSERT (nb00 == ggml_type_size (type )); 1564GGML_ASSERT (nb10 == ggml_type_size (src1 -> type )); 1565 1566// dst cannot be transposed or permuted 1567GGML_ASSERT (nb0 == sizeof (float )); 1568GGML_ASSERT (nb0 <=nb1 ); 1569GGML_ASSERT (nb1 <=nb2 ); 1570GGML_ASSERT (nb2 <=nb3 ); 1571 1572// row groups 1573const int n_ids = ids -> ne [0 ];// n_expert_used 1574const int n_as = ne02 ;// n_expert 1575 1576void * wdata_cur = params -> wdata ; 1577 1578if (src1 -> type != vec_dot_type ) { 1579incr_ptr_aligned (& wdata_cur ,ggml_row_size (vec_dot_type ,ggml_nelements (src1 )),sizeof (int64_t )); 1580 } 1581 1582int64_t * matrix_row_counts = // [n_as] 1583incr_ptr_aligned (& wdata_cur ,n_as * sizeof (int64_t ),sizeof (int64_t )); 1584 1585struct mmid_row_mapping * matrix_rows = // [n_as][ids->ne[0]*ids->ne[1]] 1586incr_ptr_aligned (& wdata_cur ,n_as * ids -> ne [0 ]* ids -> ne [1 ]* sizeof (struct mmid_row_mapping ),sizeof (int64_t )); 1587 1588char (* atomic_current_chunk )[CACHE_LINE_SIZE ]= // [n_as] 1589incr_ptr_aligned (& wdata_cur ,CACHE_LINE_SIZE * n_as ,CACHE_LINE_SIZE ); 1590 1591// IQ panel gemm (see iqp.h); per expert eligibility is decided below, but the work buffer is 1592// reserved for the whole node (ggml_graph_plan sizes it without params, use_ref only skips the dispatch) 1593const bool iqp = ggml_cpu_iqp_supports_mul_mat_id (dst )&& !params -> use_ref ; 1594 1595char * iqp_panels = NULL ; 1596 1597if (iqp ) { 1598iqp_panels = incr_ptr_aligned (& wdata_cur ,nth * ggml_cpu_iqp_scratch_size (dst ),64 ); 1599 } 1600 1601GGML_ASSERT (params -> wsize >= (size_t )((char * )wdata_cur - (char * )params -> wdata )); 1602 1603if (src1 -> type != vec_dot_type ) { 1604char * wdata = params -> wdata ; 1605 1606const size_t nbw0 = ggml_type_size (vec_dot_type ); 1607const size_t nbw1 = ggml_row_size (vec_dot_type ,ne10 ); 1608const size_t nbw2 = nbw1 * ne11 ; 1609const size_t nbw3 = nbw2 * ne12 ; 1610 1611assert (params -> wsize >=ne13 * nbw3 ); 1612GGML_ASSERT (src1 -> type == GGML_TYPE_F32 ); 1613 1614#if 0 1615for (int64_t i13 = 0 ;i13 < ne13 ;++ i13 ) { 1616for (int64_t i12 = ith ;i12 < ne12 ;i12 += nth ) { 1617for (int64_t i11 = 0 ;i11 < ne11 ;++ i11 ) { 1618from_float ((float * )((char * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 ), 1619 (void * ) (wdata + i13 * nbw3 + i12 * nbw2 + i11 * nbw1 ), 1620ne10 ); 1621 } 1622 } 1623 } 1624#else 1625for (int64_t i13 = 0 ;i13 < ne13 ;++ i13 ) { 1626for (int64_t i12 = 0 ;i12 < ne12 ;++ i12 ) { 1627for (int64_t i11 = 0 ;i11 < ne11 ;++ i11 ) { 1628size_t bs = ggml_blck_size (vec_dot_type ); 1629int64_t ne10_block_start = (ith * ne10 /bs ) /nth ; 1630int64_t ne10_block_end = ((ith + 1 )* ne10 /bs ) /nth ; 1631from_float ((float * )((char * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 + ne10_block_start * bs * nb10 ), 1632 (void * ) (wdata + i13 * nbw3 + i12 * nbw2 + i11 * nbw1 + ne10_block_start * nbw0 ), 1633 (ne10_block_end - ne10_block_start )* bs ); 1634 } 1635 } 1636 } 1637#endif 1638 } 1639 1640if (ith == 0 ) { 1641// initialize matrix_row_counts 1642memset (matrix_row_counts ,0 ,n_as * sizeof (int64_t )); 1643 1644// group rows by src0 matrix 1645for (int64_t iid1 = 0 ;iid1 < ids -> ne [1 ];++ iid1 ) { 1646for (int id = 0 ;id < n_ids ;++ id ) { 1647const int32_t i02 = * (const int32_t * ) ((const char * )ids -> data + iid1 * ids -> nb [1 ]+ id * ids -> nb [0 ]); 1648 1649assert (i02 >=0 && i02 < n_as ); 1650 1651MMID_MATRIX_ROW (i02 ,matrix_row_counts [i02 ])= (struct mmid_row_mapping ) {id ,iid1 }; 1652matrix_row_counts [i02 ]+= 1 ; 1653 } 1654 } 1655 } 1656 1657// reset current_chunk 1658for (int cur_a = ith ;cur_a < n_as ;cur_a += nth ) { 1659atomic_int * current_chunk_ctr = (atomic_int * )(atomic_current_chunk + cur_a ); 1660* current_chunk_ctr = nth ; 1661 } 1662 1663ggml_barrier (params -> threadpool ); 1664 1665for (int cur_a = 0 ;cur_a < n_as ;++ cur_a ) { 1666const int64_t cne1 = matrix_row_counts [cur_a ]; 1667 1668if (cne1 == 0 ) { 1669continue ; 1670 } 1671 1672if (iqp && ggml_cpu_iqp_mul_mat_id_min_batch (cne1 )) { 1673ggml_compute_forward_mul_mat_id_iqp (params ,dst ,cur_a ,cne1 , (const int32_t * )& MMID_MATRIX_ROW (cur_a ,0 ), 1674iqp_panels ); 1675 1676continue ; 1677 } 1678 1679const char * src0_cur = (const char * )src0 -> data + cur_a * nb02 ; 1680const void * wdata = (src1 -> type == vec_dot_type ) ?src1 -> data :params -> wdata ; 1681const size_t row_size = ggml_row_size (vec_dot_type ,ne10 ); 1682 1683const int64_t nr0 = ne01 ; 1684const int64_t nr1 = cne1 ; 1685 1686int chunk_size = 16 ; 1687if (nr0 == 1 || nr1 == 1 ) { 1688chunk_size = 64 ; 1689 } 1690 1691// disable for NUMA 1692const bool disable_chunking = ggml_is_numa (); 1693 1694int64_t nchunk0 = (nr0 + chunk_size - 1 ) /chunk_size ; 1695int64_t nchunk1 = (nr1 + chunk_size - 1 ) /chunk_size ; 1696 1697if (nchunk0 * nchunk1 < nth * 4 || disable_chunking ) { 1698nchunk0 = nr0 > nr1 ?nth :1 ; 1699nchunk1 = nr0 > nr1 ?1 :nth ; 1700 } 1701 1702const int64_t dr0 = (nr0 + nchunk0 - 1 ) /nchunk0 ; 1703const int64_t dr1 = (nr1 + nchunk1 - 1 ) /nchunk1 ; 1704 1705int current_chunk = ith ; 1706 1707atomic_int * current_chunk_ctr = (atomic_int * )(atomic_current_chunk + cur_a ); 1708 1709while (current_chunk < nchunk0 * nchunk1 ) { 1710const int64_t ith0 = current_chunk %nchunk0 ; 1711const int64_t ith1 = current_chunk /nchunk0 ; 1712 1713const int64_t ir0_start = dr0 * ith0 ; 1714const int64_t ir0_end = MIN (ir0_start + dr0 ,nr0 ); 1715 1716const int64_t ir1_start = dr1 * ith1 ; 1717const int64_t ir1_end = MIN (ir1_start + dr1 ,nr1 ); 1718 1719ggml_compute_forward_mul_mat_id_one_chunk ( 1720dst ,src0 ,src1 ,ids ,cur_a , 1721ir0_start ,ir0_end ,ir1_start ,ir1_end , 1722src0_cur ,matrix_rows ,row_size ,src1_cont ,wdata 1723 ); 1724 1725if (nth >=nchunk0 * nchunk1 ) { 1726break ; 1727 } 1728 1729current_chunk = atomic_fetch_add_explicit (current_chunk_ctr ,1 ,memory_order_relaxed ); 1730 } 1731 } 1732} 1733 1734///////////////////////////////// 1735 1736static void ggml_compute_forward (struct ggml_compute_params * params ,struct ggml_tensor * tensor ) { 1737GGML_ASSERT (params ); 1738 1739if (tensor -> op == GGML_OP_NONE || ggml_is_empty (tensor )) { 1740return ; 1741 } 1742 1743// extra_buffer op? 1744if (ggml_cpu_extra_compute_forward (params ,tensor )) { 1745return ; 1746 } 1747 1748switch (tensor -> op ) { 1749case GGML_OP_DUP : 1750 { 1751ggml_compute_forward_dup (params ,tensor ); 1752 }break ; 1753case GGML_OP_ADD : 1754 { 1755ggml_compute_forward_add (params ,tensor ); 1756 }break ; 1757case GGML_OP_ADD_ID : 1758 { 1759ggml_compute_forward_add_id (params ,tensor ); 1760 }break ; 1761case GGML_OP_ADD1 : 1762 { 1763ggml_compute_forward_add1 (params ,tensor ); 1764 }break ; 1765case GGML_OP_ACC : 1766 { 1767ggml_compute_forward_acc (params ,tensor ); 1768 }break ; 1769case GGML_OP_SUB : 1770 { 1771ggml_compute_forward_sub (params ,tensor ); 1772 }break ; 1773case GGML_OP_MUL : 1774 { 1775ggml_compute_forward_mul (params ,tensor ); 1776 }break ; 1777case GGML_OP_DIV : 1778 { 1779ggml_compute_forward_div (params ,tensor ); 1780 }break ; 1781case GGML_OP_SQR : 1782 { 1783ggml_compute_forward_sqr (params ,tensor ); 1784 }break ; 1785case GGML_OP_SQRT : 1786 { 1787ggml_compute_forward_sqrt (params ,tensor ); 1788 }break ; 1789case GGML_OP_LOG : 1790 { 1791ggml_compute_forward_log (params ,tensor ); 1792 }break ; 1793case GGML_OP_SIN : 1794 { 1795ggml_compute_forward_sin (params ,tensor ); 1796 }break ; 1797case GGML_OP_COS : 1798 { 1799ggml_compute_forward_cos (params ,tensor ); 1800 }break ; 1801case GGML_OP_SUM : 1802 { 1803ggml_compute_forward_sum (params ,tensor ); 1804 }break ; 1805case GGML_OP_SUM_ROWS : 1806 { 1807ggml_compute_forward_sum_rows (params ,tensor ); 1808 }break ; 1809case GGML_OP_CUMSUM : 1810 { 1811ggml_compute_forward_cumsum (params ,tensor ); 1812 }break ; 1813case GGML_OP_MEAN : 1814 { 1815ggml_compute_forward_mean (params ,tensor ); 1816 }break ; 1817case GGML_OP_ARGMAX : 1818 { 1819ggml_compute_forward_argmax (params ,tensor ); 1820 }break ; 1821case GGML_OP_COUNT_EQUAL : 1822 { 1823ggml_compute_forward_count_equal (params ,tensor ); 1824 }break ; 1825case GGML_OP_REPEAT : 1826 { 1827ggml_compute_forward_repeat (params ,tensor ); 1828 }break ; 1829case GGML_OP_REPEAT_BACK : 1830 { 1831ggml_compute_forward_repeat_back (params ,tensor ); 1832 }break ; 1833case GGML_OP_CONCAT : 1834 { 1835ggml_compute_forward_concat (params ,tensor ); 1836 }break ; 1837case GGML_OP_SILU_BACK : 1838 { 1839ggml_compute_forward_silu_back (params ,tensor ); 1840 }break ; 1841case GGML_OP_NORM : 1842 { 1843ggml_compute_forward_norm (params ,tensor ); 1844 }break ; 1845case GGML_OP_RMS_NORM : 1846 { 1847ggml_compute_forward_rms_norm (params ,tensor ); 1848 }break ; 1849case GGML_OP_RMS_NORM_BACK : 1850 { 1851ggml_compute_forward_rms_norm_back (params ,tensor ); 1852 }break ; 1853case GGML_OP_GROUP_NORM : 1854 { 1855ggml_compute_forward_group_norm (params ,tensor ); 1856 }break ; 1857case GGML_OP_L2_NORM : 1858 { 1859ggml_compute_forward_l2_norm (params ,tensor ); 1860 }break ; 1861case GGML_OP_MUL_MAT : 1862 { 1863ggml_compute_forward_mul_mat (params ,tensor ); 1864 }break ; 1865case GGML_OP_MUL_MAT_ID : 1866 { 1867ggml_compute_forward_mul_mat_id (params ,tensor ); 1868 }break ; 1869case GGML_OP_OUT_PROD : 1870 { 1871ggml_compute_forward_out_prod (params ,tensor ); 1872 }break ; 1873case GGML_OP_SCALE : 1874 { 1875ggml_compute_forward_scale (params ,tensor ); 1876 }break ; 1877case GGML_OP_SET : 1878 { 1879ggml_compute_forward_set (params ,tensor ); 1880 }break ; 1881case GGML_OP_CPY : 1882 { 1883ggml_compute_forward_cpy (params ,tensor ); 1884 }break ; 1885case GGML_OP_CONT : 1886 { 1887ggml_compute_forward_cont (params ,tensor ); 1888 }break ; 1889case GGML_OP_GET_ROWS : 1890 { 1891ggml_compute_forward_get_rows (params ,tensor ); 1892 }break ; 1893case GGML_OP_GET_ROWS_BACK : 1894 { 1895ggml_compute_forward_get_rows_back (params ,tensor ); 1896 }break ; 1897case GGML_OP_SET_ROWS : 1898 { 1899ggml_compute_forward_set_rows (params ,tensor ); 1900 }break ; 1901case GGML_OP_DIAG : 1902 { 1903ggml_compute_forward_diag (params ,tensor ); 1904 }break ; 1905case GGML_OP_DIAG_MASK_INF : 1906 { 1907ggml_compute_forward_diag_mask_inf (params ,tensor ); 1908 }break ; 1909case GGML_OP_DIAG_MASK_ZERO : 1910 { 1911ggml_compute_forward_diag_mask_zero (params ,tensor ); 1912 }break ; 1913case GGML_OP_SOFT_MAX : 1914 { 1915ggml_compute_forward_soft_max (params ,tensor ); 1916 }break ; 1917case GGML_OP_SOFT_MAX_BACK : 1918 { 1919ggml_compute_forward_soft_max_ext_back (params ,tensor ); 1920 }break ; 1921case GGML_OP_ROPE : 1922 { 1923ggml_compute_forward_rope (params ,tensor ); 1924 }break ; 1925case GGML_OP_ROPE_BACK : 1926 { 1927ggml_compute_forward_rope_back (params ,tensor ); 1928 }break ; 1929case GGML_OP_CLAMP : 1930 { 1931ggml_compute_forward_clamp (params ,tensor ); 1932 }break ; 1933case GGML_OP_CONV_TRANSPOSE_1D : 1934 { 1935ggml_compute_forward_conv_transpose_1d (params ,tensor ); 1936 }break ; 1937case GGML_OP_IM2COL : 1938 { 1939ggml_compute_forward_im2col (params ,tensor ); 1940 }break ; 1941case GGML_OP_IM2COL_BACK : 1942 { 1943ggml_compute_forward_im2col_back_f32 (params ,tensor ); 1944 }break ; 1945case GGML_OP_IM2COL_3D : 1946 { 1947ggml_compute_forward_im2col_3d (params ,tensor ); 1948 }break ; 1949case GGML_OP_COL2IM_1D : 1950 { 1951ggml_compute_forward_col2im_1d (params ,tensor ); 1952 }break ; 1953case GGML_OP_CONV_2D : 1954 { 1955ggml_compute_forward_conv_2d (params ,tensor ); 1956 }break ; 1957case GGML_OP_CONV_3D : 1958 { 1959ggml_compute_forward_conv_3d (params ,tensor ); 1960 }break ; 1961case GGML_OP_CONV_2D_DW : 1962 { 1963ggml_compute_forward_conv_2d_dw (params ,tensor ); 1964 }break ; 1965case GGML_OP_CONV_TRANSPOSE_2D : 1966 { 1967ggml_compute_forward_conv_transpose_2d (params ,tensor ); 1968 }break ; 1969case GGML_OP_POOL_1D : 1970 { 1971ggml_compute_forward_pool_1d (params ,tensor ); 1972 }break ; 1973case GGML_OP_POOL_2D : 1974 { 1975ggml_compute_forward_pool_2d (params ,tensor ); 1976 }break ; 1977case GGML_OP_POOL_2D_BACK : 1978 { 1979ggml_compute_forward_pool_2d_back (params ,tensor ); 1980 }break ; 1981case GGML_OP_UPSCALE : 1982 { 1983ggml_compute_forward_upscale (params ,tensor ); 1984 }break ; 1985case GGML_OP_PAD : 1986 { 1987ggml_compute_forward_pad (params ,tensor ); 1988 }break ; 1989case GGML_OP_PAD_REFLECT_1D : 1990 { 1991ggml_compute_forward_pad_reflect_1d (params ,tensor ); 1992 }break ; 1993case GGML_OP_ROLL : 1994 { 1995ggml_compute_forward_roll (params ,tensor ); 1996 }break ; 1997case GGML_OP_ARANGE : 1998 { 1999ggml_compute_forward_arange (params ,tensor ); 2000 }break ; 2001case GGML_OP_TIMESTEP_EMBEDDING : 2002 { 2003ggml_compute_forward_timestep_embedding (params ,tensor ); 2004 }break ; 2005case GGML_OP_ARGSORT : 2006 { 2007ggml_compute_forward_argsort (params ,tensor ); 2008 }break ; 2009case GGML_OP_TOP_K : 2010 { 2011ggml_compute_forward_top_k (params ,tensor ); 2012 }break ; 2013case GGML_OP_LEAKY_RELU : 2014 { 2015ggml_compute_forward_leaky_relu (params ,tensor ); 2016 }break ; 2017case GGML_OP_TRI : 2018 { 2019ggml_compute_forward_tri (params ,tensor ); 2020 }break ; 2021case GGML_OP_FILL : 2022 { 2023ggml_compute_forward_fill (params ,tensor ); 2024 }break ; 2025case GGML_OP_FLASH_ATTN_EXT : 2026 { 2027ggml_compute_forward_flash_attn_ext (params ,tensor ); 2028 }break ; 2029case GGML_OP_FLASH_ATTN_BACK : 2030 { 2031int32_t t = ggml_get_op_params_i32 (tensor ,0 ); 2032GGML_ASSERT (t == 0 || t == 1 ); 2033bool masked = t != 0 ; 2034ggml_compute_forward_flash_attn_back (params ,masked ,tensor ); 2035 }break ; 2036case GGML_OP_SSM_CONV : 2037 { 2038ggml_compute_forward_ssm_conv (params ,tensor ); 2039 }break ; 2040case GGML_OP_SSM_SCAN : 2041 { 2042ggml_compute_forward_ssm_scan (params ,tensor ); 2043 }break ; 2044case GGML_OP_WIN_PART : 2045 { 2046ggml_compute_forward_win_part (params ,tensor ); 2047 }break ; 2048case GGML_OP_WIN_UNPART : 2049 { 2050ggml_compute_forward_win_unpart (params ,tensor ); 2051 }break ; 2052case GGML_OP_UNARY : 2053 { 2054ggml_compute_forward_unary (params ,tensor ); 2055 }break ; 2056case GGML_OP_GLU : 2057 { 2058ggml_compute_forward_glu (params ,tensor ); 2059 }break ; 2060case GGML_OP_GET_REL_POS : 2061 { 2062ggml_compute_forward_get_rel_pos (params ,tensor ); 2063 }break ; 2064case GGML_OP_ADD_REL_POS : 2065 { 2066ggml_compute_forward_add_rel_pos (params ,tensor ); 2067 }break ; 2068case GGML_OP_RWKV_WKV6 : 2069 { 2070ggml_compute_forward_rwkv_wkv6 (params ,tensor ); 2071 }break ; 2072case GGML_OP_GATED_LINEAR_ATTN : 2073 { 2074ggml_compute_forward_gla (params ,tensor ); 2075 }break ; 2076case GGML_OP_RWKV_WKV7 : 2077 { 2078ggml_compute_forward_rwkv_wkv7 (params ,tensor ); 2079 }break ; 2080case GGML_OP_SOLVE_TRI : 2081 { 2082ggml_compute_forward_solve_tri (params ,tensor ); 2083 }break ; 2084case GGML_OP_GATED_DELTA_NET : 2085 { 2086ggml_compute_forward_gated_delta_net (params ,tensor ); 2087 }break ; 2088case GGML_OP_LIGHTNING_INDEXER : 2089 { 2090ggml_compute_forward_lightning_indexer (params ,tensor ); 2091 }break ; 2092case GGML_OP_DSV4_HC_COMB : 2093 { 2094ggml_compute_forward_dsv4_hc_comb (params ,tensor ); 2095 }break ; 2096case GGML_OP_DSV4_HC_PRE : 2097 { 2098ggml_compute_forward_dsv4_hc_pre (params ,tensor ); 2099 }break ; 2100case GGML_OP_DSV4_HC_POST : 2101 { 2102ggml_compute_forward_dsv4_hc_post (params ,tensor ); 2103 }break ; 2104case GGML_OP_MAP_CUSTOM1 : 2105 { 2106ggml_compute_forward_map_custom1 (params ,tensor ); 2107 } 2108break ; 2109case GGML_OP_MAP_CUSTOM2 : 2110 { 2111ggml_compute_forward_map_custom2 (params ,tensor ); 2112 } 2113break ; 2114case GGML_OP_MAP_CUSTOM3 : 2115 { 2116ggml_compute_forward_map_custom3 (params ,tensor ); 2117 } 2118break ; 2119case GGML_OP_CUSTOM : 2120 { 2121ggml_compute_forward_custom (params ,tensor ); 2122 } 2123break ; 2124case GGML_OP_CROSS_ENTROPY_LOSS : 2125 { 2126ggml_compute_forward_cross_entropy_loss (params ,tensor ); 2127 } 2128break ; 2129case GGML_OP_CROSS_ENTROPY_LOSS_BACK : 2130 { 2131ggml_compute_forward_cross_entropy_loss_back (params ,tensor ); 2132 } 2133break ; 2134case GGML_OP_OPT_STEP_ADAMW : 2135 { 2136ggml_compute_forward_opt_step_adamw (params ,tensor ); 2137 } 2138break ; 2139case GGML_OP_OPT_STEP_SGD : 2140 { 2141ggml_compute_forward_opt_step_sgd (params ,tensor ); 2142 } 2143break ; 2144case GGML_OP_NONE : 2145 { 2146// nop 2147 }break ; 2148case GGML_OP_RESHAPE : 2149 { 2150// nop 2151 }break ; 2152case GGML_OP_PERMUTE : 2153 { 2154// nop 2155 }break ; 2156case GGML_OP_VIEW : 2157 { 2158// nop 2159 }break ; 2160case GGML_OP_TRANSPOSE : 2161 { 2162// nop 2163 }break ; 2164case GGML_OP_COUNT : 2165 { 2166GGML_ABORT ("fatal error" ); 2167 } 2168 } 2169} 2170 2171// Android's libc implementation "bionic" does not support setting affinity 2172#if defined(__gnu_linux__ ) 2173static void set_numa_thread_affinity (int thread_n ) { 2174if (!ggml_is_numa ()) { 2175return ; 2176 } 2177 2178int node_num ; 2179int rv ; 2180size_t setsize = CPU_ALLOC_SIZE (g_state .numa .total_cpus ); 2181 2182switch (g_state .numa .numa_strategy ) { 2183case GGML_NUMA_STRATEGY_DISTRIBUTE : 2184// run thread on node_num thread_n / (threads per node) 2185node_num = thread_n %g_state .numa .n_nodes ; 2186break ; 2187case GGML_NUMA_STRATEGY_ISOLATE : 2188// run thread on current_node 2189node_num = g_state .numa .current_node ; 2190break ; 2191case GGML_NUMA_STRATEGY_NUMACTL : 2192// use the cpuset that numactl gave us 2193rv = pthread_setaffinity_np (pthread_self (),setsize ,& g_state .numa .cpuset ); 2194if (rv ) { 2195fprintf (stderr ,"warning: pthread_setaffinity_np() failed: %s\n" ,strerror (rv )); 2196 } 2197return ; 2198default : 2199return ; 2200 } 2201 2202struct ggml_numa_node * node = & g_state .numa .nodes [node_num ]; 2203 2204cpu_set_t * cpus = CPU_ALLOC (g_state .numa .total_cpus ); 2205CPU_ZERO_S (setsize ,cpus ); 2206for (size_t i = 0 ;i < node -> n_cpus ;++ i ) { 2207CPU_SET_S (node -> cpus [i ],setsize ,cpus ); 2208 } 2209 2210rv = pthread_setaffinity_np (pthread_self (),setsize ,cpus ); 2211if (rv ) { 2212fprintf (stderr ,"warning: pthread_setaffinity_np() failed: %s\n" ,strerror (rv )); 2213 } 2214 2215CPU_FREE (cpus ); 2216} 2217 2218static void clear_numa_thread_affinity (void ) { 2219if (!ggml_is_numa ()) { 2220return ; 2221 } 2222 2223size_t setsize = CPU_ALLOC_SIZE (g_state .numa .total_cpus ); 2224 2225cpu_set_t * cpus = CPU_ALLOC (g_state .numa .total_cpus ); 2226CPU_ZERO_S (setsize ,cpus ); 2227for (unsigned i = 0 ;i < g_state .numa .total_cpus ;++ i ) { 2228CPU_SET_S (i ,setsize ,cpus ); 2229 } 2230 2231int rv = pthread_setaffinity_np (pthread_self (),setsize ,cpus ); 2232if (rv ) { 2233fprintf (stderr ,"warning: pthread_setaffinity_np() failed: %s\n" ,strerror (rv )); 2234 } 2235 2236CPU_FREE (cpus ); 2237} 2238#else 2239// TODO: Windows etc. 2240// (the linux implementation may also work on BSD, someone should test) 2241static void set_numa_thread_affinity (int thread_n ) {UNUSED (thread_n ); } 2242static void clear_numa_thread_affinity (void ) {} 2243#endif 2244 2245static int ggml_get_n_tasks (struct ggml_tensor * node ,int n_threads ) { 2246int n_tasks = 0 ; 2247 2248if (ggml_is_empty (node )) { 2249// no need to multi-thread a no-op 2250n_tasks = 1 ; 2251return n_tasks ; 2252 } 2253 2254switch (node -> op ) { 2255case GGML_OP_CPY : 2256case GGML_OP_DUP : 2257case GGML_OP_CONT : 2258case GGML_OP_ADD : 2259case GGML_OP_ADD_ID : 2260case GGML_OP_ADD1 : 2261case GGML_OP_ACC : 2262case GGML_OP_CUMSUM : 2263case GGML_OP_TRI : 2264case GGML_OP_FILL : 2265 { 2266n_tasks = n_threads ; 2267 }break ; 2268case GGML_OP_SUB : 2269case GGML_OP_SQR : 2270case GGML_OP_SQRT : 2271case GGML_OP_LOG : 2272case GGML_OP_SIN : 2273case GGML_OP_COS : 2274case GGML_OP_SUM : 2275case GGML_OP_SUM_ROWS : 2276case GGML_OP_MEAN : 2277case GGML_OP_ARGMAX : 2278 { 2279n_tasks = 1 ; 2280 }break ; 2281case GGML_OP_COUNT_EQUAL : 2282case GGML_OP_SOLVE_TRI : 2283case GGML_OP_GATED_DELTA_NET : 2284case GGML_OP_DSV4_HC_COMB : 2285case GGML_OP_DSV4_HC_PRE : 2286case GGML_OP_DSV4_HC_POST : 2287 { 2288n_tasks = n_threads ; 2289 }break ; 2290case GGML_OP_REPEAT : 2291case GGML_OP_REPEAT_BACK : 2292case GGML_OP_LEAKY_RELU : 2293 { 2294n_tasks = 1 ; 2295 }break ; 2296case GGML_OP_UNARY : 2297switch (ggml_get_unary_op (node )) { 2298case GGML_UNARY_OP_ABS : 2299case GGML_UNARY_OP_SGN : 2300case GGML_UNARY_OP_NEG : 2301case GGML_UNARY_OP_STEP : 2302case GGML_UNARY_OP_TANH : 2303case GGML_UNARY_OP_ELU : 2304case GGML_UNARY_OP_RELU : 2305case GGML_UNARY_OP_SIGMOID : 2306case GGML_UNARY_OP_HARDSWISH : 2307case GGML_UNARY_OP_HARDSIGMOID : 2308case GGML_UNARY_OP_EXP : 2309case GGML_UNARY_OP_SOFTPLUS : 2310case GGML_UNARY_OP_EXPM1 : 2311case GGML_UNARY_OP_FLOOR : 2312case GGML_UNARY_OP_CEIL : 2313case GGML_UNARY_OP_ROUND : 2314case GGML_UNARY_OP_TRUNC : 2315 { 2316n_tasks = 1 ; 2317 }break ; 2318 2319case GGML_UNARY_OP_GELU : 2320case GGML_UNARY_OP_GELU_ERF : 2321case GGML_UNARY_OP_GELU_QUICK : 2322case GGML_UNARY_OP_SILU : 2323case GGML_UNARY_OP_XIELU : 2324 { 2325n_tasks = n_threads ; 2326 }break ; 2327default : 2328GGML_ABORT ("fatal error" ); 2329 } 2330break ; 2331case GGML_OP_GLU : 2332switch (ggml_get_glu_op (node )) { 2333case GGML_GLU_OP_REGLU : 2334case GGML_GLU_OP_GEGLU : 2335case GGML_GLU_OP_SWIGLU : 2336case GGML_GLU_OP_SWIGLU_OAI : 2337case GGML_GLU_OP_GEGLU_ERF : 2338case GGML_GLU_OP_GEGLU_QUICK : 2339case GGML_GLU_OP_SWIGLU_CLAMP : 2340 { 2341n_tasks = n_threads ; 2342 }break ; 2343default : 2344GGML_ABORT ("fatal error" ); 2345 } 2346break ; 2347case GGML_OP_SILU_BACK : 2348case GGML_OP_MUL : 2349case GGML_OP_DIV : 2350case GGML_OP_NORM : 2351case GGML_OP_RMS_NORM : 2352case GGML_OP_RMS_NORM_BACK : 2353case GGML_OP_L2_NORM : 2354case GGML_OP_GROUP_NORM : 2355case GGML_OP_CONCAT : 2356case GGML_OP_MUL_MAT : 2357case GGML_OP_MUL_MAT_ID : 2358case GGML_OP_OUT_PROD : 2359 { 2360n_tasks = n_threads ; 2361 }break ; 2362case GGML_OP_GET_ROWS : 2363case GGML_OP_SET_ROWS : 2364 { 2365// FIXME: get_rows can use additional threads, but the cost of launching additional threads 2366// decreases performance with GPU offloading 2367//n_tasks = n_threads; 2368n_tasks = 1 ; 2369 }break ; 2370case GGML_OP_SCALE : 2371case GGML_OP_SET : 2372case GGML_OP_RESHAPE : 2373case GGML_OP_VIEW : 2374case GGML_OP_PERMUTE : 2375case GGML_OP_TRANSPOSE : 2376case GGML_OP_GET_ROWS_BACK : 2377case GGML_OP_DIAG : 2378 { 2379n_tasks = 1 ; 2380 }break ; 2381case GGML_OP_DIAG_MASK_ZERO : 2382case GGML_OP_DIAG_MASK_INF : 2383case GGML_OP_SOFT_MAX_BACK : 2384case GGML_OP_ROPE : 2385case GGML_OP_ROPE_BACK : 2386case GGML_OP_ADD_REL_POS : 2387 { 2388n_tasks = n_threads ; 2389 }break ; 2390case GGML_OP_CLAMP : 2391 { 2392n_tasks = 1 ;//TODO 2393 }break ; 2394case GGML_OP_SOFT_MAX : 2395 { 2396n_tasks = MIN (n_threads ,ggml_nrows (node -> src [0 ])); 2397 }break ; 2398case GGML_OP_IM2COL : 2399case GGML_OP_IM2COL_BACK : 2400case GGML_OP_IM2COL_3D : 2401case GGML_OP_CONV_2D : 2402case GGML_OP_CONV_3D : 2403case GGML_OP_CONV_2D_DW : 2404case GGML_OP_COL2IM_1D : 2405case GGML_OP_CONV_TRANSPOSE_1D : 2406case GGML_OP_CONV_TRANSPOSE_2D : 2407 { 2408n_tasks = n_threads ; 2409 }break ; 2410case GGML_OP_POOL_1D : 2411case GGML_OP_POOL_2D : 2412case GGML_OP_POOL_2D_BACK : 2413 { 2414n_tasks = 1 ; 2415 }break ; 2416case GGML_OP_UPSCALE : 2417case GGML_OP_PAD : 2418case GGML_OP_PAD_REFLECT_1D : 2419case GGML_OP_ROLL : 2420case GGML_OP_ARANGE : 2421case GGML_OP_TIMESTEP_EMBEDDING : 2422case GGML_OP_ARGSORT : 2423case GGML_OP_TOP_K : 2424case GGML_OP_FLASH_ATTN_EXT : 2425case GGML_OP_FLASH_ATTN_BACK : 2426case GGML_OP_SSM_CONV : 2427case GGML_OP_SSM_SCAN : 2428case GGML_OP_LIGHTNING_INDEXER : 2429 { 2430n_tasks = n_threads ; 2431 }break ; 2432case GGML_OP_RWKV_WKV6 : 2433case GGML_OP_GATED_LINEAR_ATTN : 2434case GGML_OP_RWKV_WKV7 : 2435 { 2436const int64_t n_heads = node -> src [1 ]-> ne [1 ]; 2437n_tasks = MIN (n_threads ,n_heads ); 2438 }break ; 2439case GGML_OP_WIN_PART : 2440case GGML_OP_WIN_UNPART : 2441case GGML_OP_GET_REL_POS : 2442 { 2443n_tasks = 1 ; 2444 }break ; 2445case GGML_OP_MAP_CUSTOM1 : 2446 { 2447struct ggml_map_custom1_op_params p ; 2448memcpy (& p ,node -> op_params ,sizeof (p )); 2449if (p .n_tasks == GGML_N_TASKS_MAX ) { 2450n_tasks = n_threads ; 2451 }else { 2452n_tasks = MIN (p .n_tasks ,n_threads ); 2453 } 2454 }break ; 2455case GGML_OP_MAP_CUSTOM2 : 2456 { 2457struct ggml_map_custom2_op_params p ; 2458memcpy (& p ,node -> op_params ,sizeof (p )); 2459if (p .n_tasks == GGML_N_TASKS_MAX ) { 2460n_tasks = n_threads ; 2461 }else { 2462n_tasks = MIN (p .n_tasks ,n_threads ); 2463 } 2464 }break ; 2465case GGML_OP_MAP_CUSTOM3 : 2466 { 2467struct ggml_map_custom3_op_params p ; 2468memcpy (& p ,node -> op_params ,sizeof (p )); 2469if (p .n_tasks == GGML_N_TASKS_MAX ) { 2470n_tasks = n_threads ; 2471 }else { 2472n_tasks = MIN (p .n_tasks ,n_threads ); 2473 } 2474 }break ; 2475case GGML_OP_CUSTOM : 2476 { 2477struct ggml_custom_op_params p ; 2478memcpy (& p ,node -> op_params ,sizeof (p )); 2479if (p .n_tasks == GGML_N_TASKS_MAX ) { 2480n_tasks = n_threads ; 2481 }else { 2482n_tasks = MIN (p .n_tasks ,n_threads ); 2483 } 2484 }break ; 2485case GGML_OP_CROSS_ENTROPY_LOSS : 2486case GGML_OP_CROSS_ENTROPY_LOSS_BACK : 2487case GGML_OP_OPT_STEP_ADAMW : 2488case GGML_OP_OPT_STEP_SGD : 2489 { 2490n_tasks = n_threads ; 2491 }break ; 2492case GGML_OP_NONE : 2493 { 2494n_tasks = 1 ; 2495 }break ; 2496case GGML_OP_COUNT : 2497 { 2498GGML_ABORT ("fatal error" ); 2499 } 2500default : 2501 { 2502fprintf (stderr ,"%s: op not implemented: " ,__func__ ); 2503if (node -> op < GGML_OP_COUNT ) { 2504fprintf (stderr ,"%s\n" ,ggml_op_name (node -> op )); 2505 }else { 2506fprintf (stderr ,"%d\n" ,node -> op ); 2507 } 2508GGML_ABORT ("fatal error" ); 2509 } 2510 } 2511 2512assert (n_tasks > 0 ); 2513 2514return n_tasks ; 2515} 2516 2517static thread_ret_t ggml_graph_compute_secondary_thread (void * data ); 2518 2519#if defined(_WIN32 ) 2520#include "windows.h" 2521 2522// TODO: support > 64 CPUs 2523static bool ggml_thread_apply_affinity (bool * mask ) { 2524HANDLE h = GetCurrentThread (); 2525uint64_t bitmask = 0ULL ; 2526 2527assert (GGML_MAX_N_THREADS >=64 ); 2528 2529for (int32_t i = 0 ;i < 8 ;i ++ ) { 2530int32_t idx = i * 8 ; 2531uint8_t val = 0 ; 2532val |=mask [idx + 0 ] <<0 ; 2533val |=mask [idx + 1 ] <<1 ; 2534val |=mask [idx + 2 ] <<2 ; 2535val |=mask [idx + 3 ] <<3 ; 2536val |=mask [idx + 4 ] <<4 ; 2537val |=mask [idx + 5 ] <<5 ; 2538val |=mask [idx + 6 ] <<6 ; 2539val |=mask [idx + 7 ] <<7 ; 2540bitmask |= (uint64_t )val <<idx ; 2541 } 2542 2543for (int32_t i = 64 ;i < GGML_MAX_N_THREADS ;i ++ ) { 2544if (mask [i ]) { 2545fprintf (stderr ,"warn: setting thread-affinity for > 64 CPUs isn't supported on windows!\n" ); 2546break ; 2547 } 2548 } 2549 2550DWORD_PTR m = (DWORD_PTR )bitmask ; 2551 2552m = SetThreadAffinityMask (h ,m ); 2553 2554return m != 0 ; 2555} 2556 2557static bool ggml_thread_apply_priority (int32_t prio ) { 2558// Note that on Windows the Process Priority Class must be updated in order to set Thread priority. 2559// This is up to the applications. 2560DWORD p = THREAD_PRIORITY_NORMAL ; 2561switch (prio ) { 2562case GGML_SCHED_PRIO_LOW :p = THREAD_PRIORITY_BELOW_NORMAL ;break ; 2563case GGML_SCHED_PRIO_NORMAL :p = THREAD_PRIORITY_NORMAL ;break ; 2564case GGML_SCHED_PRIO_MEDIUM :p = THREAD_PRIORITY_ABOVE_NORMAL ;break ; 2565case GGML_SCHED_PRIO_HIGH :p = THREAD_PRIORITY_HIGHEST ;break ; 2566case GGML_SCHED_PRIO_REALTIME :p = THREAD_PRIORITY_TIME_CRITICAL ;break ; 2567 } 2568 2569if (prio != GGML_SCHED_PRIO_LOW ) { 2570// Tell Windows that this thread should not be throttled (needs its own CPU core). 2571// Newer Windows 11 versions aggressively park (offline) CPU cores and often place 2572// all our threads onto the first 4 cores which results in terrible performance with 2573// n_threads > 4 2574#if _WIN32_WINNT >=0x0602 2575THREAD_POWER_THROTTLING_STATE t ; 2576ZeroMemory (& t ,sizeof (t )); 2577t .Version = THREAD_POWER_THROTTLING_CURRENT_VERSION ; 2578t .ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED ; 2579t .StateMask = 0 ; 2580 2581if (!SetThreadInformation (GetCurrentThread (),ThreadPowerThrottling ,& t ,sizeof (t ))) { 2582GGML_LOG_DEBUG ("failed to disable thread power throttling %d : (%d)\n" ,prio , (int )GetLastError ()); 2583return false; 2584 } 2585#endif 2586 } 2587 2588if (prio == GGML_SCHED_PRIO_NORMAL ) { 2589// Keep inherited policy/priority 2590return true; 2591 } 2592 2593if (!SetThreadPriority (GetCurrentThread (),p )) { 2594fprintf (stderr ,"warn: failed to set thread priority %d : (%d)\n" ,prio , (int )GetLastError ()); 2595return false; 2596 } 2597 2598return true; 2599} 2600 2601#elif defined(__APPLE__ ) 2602#include <sys/types.h> 2603#include <sys/resource.h> 2604 2605static bool ggml_thread_apply_affinity (const bool * mask ) { 2606// Not supported on Apple platforms 2607UNUSED (mask ); 2608return true; 2609} 2610 2611static bool ggml_thread_apply_priority (int32_t prio ) { 2612struct sched_param p ; 2613int32_t policy = SCHED_OTHER ; 2614switch (prio ) { 2615// TODO: there seems to be no way to set lower prio on Apple platforms 2616case GGML_SCHED_PRIO_LOW :policy = SCHED_OTHER ;p .sched_priority = 0 ;break ; 2617case GGML_SCHED_PRIO_NORMAL :policy = SCHED_OTHER ;p .sched_priority = 0 ;break ; 2618case GGML_SCHED_PRIO_MEDIUM :policy = SCHED_FIFO ;p .sched_priority = 40 ;break ; 2619case GGML_SCHED_PRIO_HIGH :policy = SCHED_FIFO ;p .sched_priority = 80 ;break ; 2620case GGML_SCHED_PRIO_REALTIME :policy = SCHED_FIFO ;p .sched_priority = 90 ;break ; 2621 } 2622 2623if (prio == GGML_SCHED_PRIO_NORMAL ) { 2624// Keep inherited policy/priority 2625return true; 2626 } 2627 2628int32_t err = pthread_setschedparam (pthread_self (),policy ,& p ); 2629if (err != 0 ) { 2630fprintf (stderr ,"warn: failed to set thread priority %d : %s (%d)\n" ,prio ,strerror (err ),err ); 2631return false; 2632 } 2633 2634return true; 2635} 2636 2637#elif defined(__linux__ ) 2638// TODO: this may not work on BSD, to be verified 2639 2640static bool ggml_thread_apply_affinity (const bool * mask ) { 2641cpu_set_t cpuset ; 2642int err ; 2643 2644CPU_ZERO (& cpuset ); 2645 2646for (uint32_t i = 0 ;i < GGML_MAX_N_THREADS ;i ++ ) { 2647if (mask [i ]) { 2648GGML_PRINT_DEBUG ("Thread %lx: adding %d to cpuset\n" ,pthread_self (),i ); 2649CPU_SET (i ,& cpuset ); 2650 } 2651 } 2652 2653#ifdef __ANDROID__ 2654err = sched_setaffinity (0 ,sizeof (cpuset ),& cpuset ); 2655if (err < 0 ) { 2656err = errno ; 2657 } 2658#else 2659err = pthread_setaffinity_np (pthread_self (),sizeof (cpuset ),& cpuset ); 2660#endif 2661if (err != 0 ) { 2662fprintf (stderr ,"warn: failed to set affinity mask 0x%llx : %s (%d)\n" , (unsigned long long )mask ,strerror (err ),err ); 2663return false; 2664 } 2665 2666return true; 2667} 2668 2669static bool ggml_thread_apply_priority (int32_t prio ) { 2670struct sched_param p ; 2671int32_t policy = SCHED_OTHER ; 2672switch (prio ) { 2673case GGML_SCHED_PRIO_LOW :policy = SCHED_BATCH ;p .sched_priority = 0 ;break ; 2674case GGML_SCHED_PRIO_NORMAL :policy = SCHED_OTHER ;p .sched_priority = 0 ;break ; 2675case GGML_SCHED_PRIO_MEDIUM :policy = SCHED_FIFO ;p .sched_priority = 40 ;break ; 2676case GGML_SCHED_PRIO_HIGH :policy = SCHED_FIFO ;p .sched_priority = 80 ;break ; 2677case GGML_SCHED_PRIO_REALTIME :policy = SCHED_FIFO ;p .sched_priority = 90 ;break ; 2678 } 2679 2680if (prio == GGML_SCHED_PRIO_NORMAL ) { 2681// Keep inherited policy/priority 2682return true; 2683 } 2684 2685int32_t err = pthread_setschedparam (pthread_self (),policy ,& p ); 2686if (err != 0 ) { 2687fprintf (stderr ,"warn: failed to set thread priority %d : %s (%d)\n" ,prio ,strerror (err ),err ); 2688return false; 2689 } 2690 2691return true; 2692} 2693 2694#else // unsupported platforms 2695 2696static bool ggml_thread_apply_affinity (const bool * mask ) { 2697UNUSED (mask ); 2698return true; 2699} 2700 2701static bool ggml_thread_apply_priority (int32_t prio ) { 2702UNUSED (prio ); 2703return true; 2704} 2705 2706#endif 2707 2708static bool ggml_thread_cpumask_is_valid (const bool * mask ) { 2709for (int i = 0 ;i < GGML_MAX_N_THREADS ;i ++ ) { 2710if (mask [i ]) {return true; } 2711 } 2712return false; 2713} 2714 2715static void ggml_thread_cpumask_next (const bool * global_mask ,bool * local_mask ,bool strict ,int32_t * iter ) { 2716if (!strict ) { 2717memcpy (local_mask ,global_mask ,GGML_MAX_N_THREADS ); 2718return ; 2719 }else { 2720memset (local_mask ,0 ,GGML_MAX_N_THREADS ); 2721int32_t base_idx = * iter ; 2722for (int32_t i = 0 ;i < GGML_MAX_N_THREADS ;i ++ ) { 2723int32_t idx = base_idx + i ; 2724if (idx >=GGML_MAX_N_THREADS ) { 2725// Just a cheaper modulo 2726idx -= GGML_MAX_N_THREADS ; 2727 } 2728if (global_mask [idx ]) { 2729local_mask [idx ]= 1 ; 2730* iter = idx + 1 ; 2731return ; 2732 } 2733 } 2734 } 2735} 2736 2737void ggml_threadpool_free (struct ggml_threadpool * threadpool ) { 2738if (!threadpool )return ; 2739 2740const int n_threads = threadpool -> n_threads ; 2741 2742#ifndef GGML_USE_OPENMP 2743struct ggml_compute_state * workers = threadpool -> workers ; 2744 2745ggml_mutex_lock (& threadpool -> mutex ); 2746 2747threadpool -> stop = true; 2748threadpool -> pause = false; 2749 2750ggml_cond_broadcast (& threadpool -> cond ); 2751ggml_mutex_unlock (& threadpool -> mutex ); 2752 2753for (int j = 1 ;j < n_threads ;j ++ ) { 2754int32_t rc = ggml_thread_join (workers [j ].thrd ,NULL ); 2755GGML_ASSERT (rc == GGML_EXIT_SUCCESS || rc == GGML_EXIT_ABORTED ); 2756UNUSED (rc ); 2757 } 2758 2759ggml_mutex_destroy (& threadpool -> mutex ); 2760ggml_cond_destroy (& threadpool -> cond ); 2761#endif // GGML_USE_OPENMP 2762 2763const size_t workers_size = sizeof (struct ggml_compute_state )* n_threads ; 2764ggml_aligned_free (threadpool -> workers ,workers_size ); 2765ggml_aligned_free (threadpool ,sizeof (struct ggml_threadpool )); 2766} 2767 2768#ifndef GGML_USE_OPENMP 2769// pause/resume must be called under mutex 2770static void ggml_threadpool_pause_locked (struct ggml_threadpool * threadpool ) { 2771GGML_PRINT_DEBUG ("Pausing threadpool\n" ); 2772threadpool -> pause = true; 2773ggml_cond_broadcast (& threadpool -> cond ); 2774} 2775 2776static void ggml_threadpool_resume_locked (struct ggml_threadpool * threadpool ) { 2777GGML_PRINT_DEBUG ("Resuming threadpool\n" ); 2778threadpool -> pause = false; 2779ggml_cond_broadcast (& threadpool -> cond ); 2780} 2781#endif 2782 2783void ggml_threadpool_pause (struct ggml_threadpool * threadpool ) { 2784#ifndef GGML_USE_OPENMP 2785ggml_mutex_lock (& threadpool -> mutex ); 2786if (!threadpool -> pause ) { 2787ggml_threadpool_pause_locked (threadpool ); 2788 } 2789ggml_mutex_unlock (& threadpool -> mutex ); 2790#else 2791UNUSED (threadpool ); 2792#endif 2793} 2794 2795void ggml_threadpool_resume (struct ggml_threadpool * threadpool ) { 2796#ifndef GGML_USE_OPENMP 2797ggml_mutex_lock (& threadpool -> mutex ); 2798if (threadpool -> pause ) { 2799ggml_threadpool_resume_locked (threadpool ); 2800 } 2801ggml_mutex_unlock (& threadpool -> mutex ); 2802#else 2803UNUSED (threadpool ); 2804#endif 2805} 2806 2807struct ggml_cplan ggml_graph_plan ( 2808const struct ggml_cgraph * cgraph , 2809int n_threads , 2810struct ggml_threadpool * threadpool ) { 2811 2812if (threadpool == NULL ) { 2813//GGML_PRINT_DEBUG("Threadpool is not specified. Will create a disposable threadpool : n_threads %d\n", n_threads); 2814 } 2815if (n_threads <=0 ) { 2816n_threads = threadpool ?threadpool -> n_threads :GGML_DEFAULT_N_THREADS ; 2817 } 2818 2819#if defined(__EMSCRIPTEN__ )&& !defined(__EMSCRIPTEN_PTHREADS__ ) 2820// Emscripten without pthreads support can only use a single thread 2821n_threads = 1 ; 2822#endif 2823 2824#if defined(__wasi__ ) 2825// WASI doesn't support parallelism yet 2826n_threads = 1 ; 2827#endif 2828 2829size_t work_size = 0 ; 2830 2831struct ggml_cplan cplan ; 2832memset (& cplan ,0 ,sizeof (struct ggml_cplan )); 2833 2834int max_tasks = 1 ; 2835 2836// thread scheduling for the different operations + work buffer size estimation 2837for (int i = 0 ;i < cgraph -> n_nodes ;i ++ ) { 2838struct ggml_tensor * node = cgraph -> nodes [i ]; 2839 2840const int n_tasks = ggml_get_n_tasks (node ,n_threads ); 2841 2842max_tasks = MAX (max_tasks ,n_tasks ); 2843 2844size_t cur = 0 ; 2845 2846if (!ggml_cpu_extra_work_size (n_threads ,node ,& cur )) { 2847switch (node -> op ) { 2848case GGML_OP_CPY : 2849case GGML_OP_DUP : 2850 { 2851if (ggml_is_quantized (node -> type )|| 2852// F16 -> BF16 and BF16 -> F16 copies go through intermediate F32 2853 (node -> src [0 ]-> type == GGML_TYPE_F16 && node -> src [1 ]&& node -> src [1 ]-> type == GGML_TYPE_BF16 )|| 2854 (node -> src [0 ]-> type == GGML_TYPE_BF16 && node -> src [1 ]&& node -> src [1 ]-> type == GGML_TYPE_F16 )|| 2855// conversion between F32 and I32 2856 (node -> src [0 ]-> type == GGML_TYPE_F32 && node -> src [1 ]&& node -> src [1 ]-> type == GGML_TYPE_I32 )|| 2857 (node -> src [0 ]-> type == GGML_TYPE_I32 && node -> src [1 ]&& node -> src [1 ]-> type == GGML_TYPE_F32 )) { 2858cur = ggml_type_size (GGML_TYPE_F32 )* node -> ne [0 ]* n_tasks ; 2859 } 2860 }break ; 2861case GGML_OP_ADD : 2862case GGML_OP_ADD_ID : 2863case GGML_OP_ADD1 : 2864 { 2865if (ggml_is_quantized (node -> src [0 ]-> type )) { 2866cur = ggml_type_size (GGML_TYPE_F32 )* node -> src [0 ]-> ne [0 ]* n_tasks ; 2867 } 2868 }break ; 2869case GGML_OP_ACC : 2870 { 2871if (ggml_is_quantized (node -> src [0 ]-> type )) { 2872cur = ggml_type_size (GGML_TYPE_F32 )* node -> src [1 ]-> ne [0 ]* n_tasks ; 2873 } 2874 }break ; 2875case GGML_OP_COUNT_EQUAL : 2876 { 2877cur = ggml_type_size (node -> type )* n_tasks ; 2878 }break ; 2879case GGML_OP_MUL_MAT : 2880 { 2881const enum ggml_type vec_dot_type = type_traits_cpu [node -> src [0 ]-> type ].vec_dot_type ; 2882 2883if (node -> src [1 ]-> type != vec_dot_type ) { 2884cur = ggml_row_size (vec_dot_type ,ggml_nelements (node -> src [1 ])); 2885 } 2886 2887// the IQ panel path needs one scratch panel per thread past the q8_K rows 2888if (ggml_cpu_iqp_supports_mul_mat (node )) { 2889cur = GGML_PAD (cur ,64 )+ n_tasks * ggml_cpu_iqp_scratch_size (node ); 2890 } 2891 }break ; 2892case GGML_OP_MUL_MAT_ID : 2893 { 2894cur = 0 ; 2895const struct ggml_tensor * src0 = node -> src [0 ]; 2896const struct ggml_tensor * src1 = node -> src [1 ]; 2897const struct ggml_tensor * ids = node -> src [2 ]; 2898const enum ggml_type vec_dot_type = type_traits_cpu [src0 -> type ].vec_dot_type ; 2899const int n_as = src0 -> ne [2 ]; 2900// src1 2901if (src1 -> type != vec_dot_type ) { 2902cur += ggml_row_size (vec_dot_type ,ggml_nelements (src1 ))+ sizeof (int64_t ); 2903 } 2904// matrix_row_counts 2905cur += n_as * sizeof (int64_t )+ sizeof (int64_t ); 2906// matrix_rows 2907cur += n_as * ids -> ne [0 ]* ids -> ne [1 ]* sizeof (struct mmid_row_mapping )+ sizeof (int64_t ); 2908// atomic_current_chunk 2909cur += CACHE_LINE_SIZE * n_as + CACHE_LINE_SIZE ; 2910// the IQ panel path needs one scratch panel per thread on top of that 2911if (ggml_cpu_iqp_supports_mul_mat_id (node )) { 2912cur += n_tasks * ggml_cpu_iqp_scratch_size (node )+ 64 ; 2913 } 2914 }break ; 2915case GGML_OP_OUT_PROD : 2916 { 2917if (ggml_is_quantized (node -> src [0 ]-> type )|| 2918node -> src [0 ]-> type == GGML_TYPE_F16 ) { 2919cur = ggml_type_size (GGML_TYPE_F32 )* node -> src [0 ]-> ne [0 ]* n_tasks ; 2920 } 2921 }break ; 2922case GGML_OP_SET_ROWS : 2923 { 2924if (node -> src [0 ]-> type == GGML_TYPE_F16 && node -> type != GGML_TYPE_F16 ) { 2925cur = ggml_type_size (GGML_TYPE_F32 )* node -> src [0 ]-> ne [0 ]* n_tasks ; 2926 } 2927 }break ; 2928case GGML_OP_SOFT_MAX : 2929case GGML_OP_ROPE : 2930case GGML_OP_ROPE_BACK : 2931 { 2932cur = ggml_type_size (GGML_TYPE_F32 )* node -> ne [0 ]* n_tasks ; 2933 }break ; 2934case GGML_OP_CONV_TRANSPOSE_1D : 2935 { 2936GGML_ASSERT (node -> src [0 ]-> ne [3 ]== 1 ); 2937GGML_ASSERT (node -> src [1 ]-> ne [2 ]== 1 ); 2938GGML_ASSERT (node -> src [1 ]-> ne [3 ]== 1 ); 2939 2940const int64_t ne00 = node -> src [0 ]-> ne [0 ];// K 2941const int64_t ne01 = node -> src [0 ]-> ne [1 ];// Cout 2942const int64_t ne02 = node -> src [0 ]-> ne [2 ];// Cin 2943const int64_t ne10 = node -> src [1 ]-> ne [0 ];// L 2944const int64_t ne11 = node -> src [1 ]-> ne [1 ];// Cin 2945 2946if ((node -> src [0 ]-> type == GGML_TYPE_F16 || 2947node -> src [0 ]-> type == GGML_TYPE_BF16 )&& 2948node -> src [1 ]-> type == GGML_TYPE_F32 ) { 2949cur += sizeof (ggml_fp16_t )* ne00 * ne01 * ne02 ; 2950cur += sizeof (ggml_fp16_t )* ne10 * ne11 ; 2951 }else if (node -> src [0 ]-> type == GGML_TYPE_F32 && 2952node -> src [1 ]-> type == GGML_TYPE_F32 ) { 2953cur += sizeof (float )* ne00 * ne01 * ne02 ; 2954cur += sizeof (float )* ne10 * ne11 ; 2955 }else { 2956GGML_ABORT ("fatal error" ); 2957 } 2958 }break ; 2959case GGML_OP_CONV_2D : 2960case GGML_OP_CONV_3D : 2961 { 2962cur = GGML_IM2COL_WORK_SIZE ; 2963 }break ; 2964case GGML_OP_CONV_TRANSPOSE_2D : 2965 { 2966const int64_t ne00 = node -> src [0 ]-> ne [0 ];// W 2967const int64_t ne01 = node -> src [0 ]-> ne [1 ];// H 2968const int64_t ne02 = node -> src [0 ]-> ne [2 ];// Channels Out 2969const int64_t ne03 = node -> src [0 ]-> ne [3 ];// Channels In 2970 2971const int64_t ne10 = node -> src [1 ]-> ne [0 ];// W 2972const int64_t ne11 = node -> src [1 ]-> ne [1 ];// H 2973const int64_t ne12 = node -> src [1 ]-> ne [2 ];// Channels In 2974const int64_t ne13 = node -> src [1 ]-> ne [3 ];// Batch 2975 2976GGML_ASSERT (node -> src [0 ]-> type == GGML_TYPE_F16 || node -> src [0 ]-> type == GGML_TYPE_F32 ); 2977GGML_ASSERT (node -> src [1 ]-> type == GGML_TYPE_F32 ); 2978 2979cur += ggml_type_size (node -> src [0 ]-> type )* ne00 * ne01 * ne02 * ne03 ; 2980cur += ggml_type_size (node -> src [0 ]-> type )* ne10 * ne11 * ne12 * ne13 ; 2981 2982 }break ; 2983case GGML_OP_TOP_K : 2984 { 2985cur += sizeof (int32_t )* node -> src [0 ]-> ne [0 ]* n_tasks ; 2986 }break ; 2987case GGML_OP_FLASH_ATTN_EXT : 2988 { 2989const int64_t neq2 = node -> src [0 ]-> ne [2 ];// number of query heads 2990const int64_t DK = node -> src [1 ]-> ne [0 ]; 2991const int64_t DV = node -> src [2 ]-> ne [0 ]; 2992 2993// Tiled flash attention scratch (tile sizes defined in common.h) 2994// Per-thread: Q_q + KQ + mask + VKQ32 + V32 + K_f32 + padding 2995size_t prefill = sizeof (float )* (GGML_FA_TILE_Q * DK + 2 * GGML_FA_TILE_Q * GGML_FA_TILE_KV + GGML_FA_TILE_Q * DV + GGML_FA_TILE_KV * DV + GGML_FA_TILE_KV * DK )* n_tasks ; 2996 2997// Decode path: n_kv_chunks = n_tasks (one chunk per thread) 2998// Per-thread: VKQ accmulator (DV), partial M, partial S + intra-thread scratch for V, Q and VKQ 2999size_t n_chunks = n_tasks ; 3000size_t decode = sizeof (float )* (neq2 * n_chunks * (2 + DV )+ n_tasks * (DK + 2 * DV )); 3001 3002cur += MAX (prefill ,decode ); 3003 }break ; 3004case GGML_OP_FLASH_ATTN_BACK : 3005 { 3006const int64_t D = node -> src [0 ]-> ne [0 ]; 3007const int64_t ne11 = ggml_up (node -> src [1 ]-> ne [1 ],GGML_SOFT_MAX_UNROLL ); 3008const int64_t mxDn = MAX (D ,ne11 )* 2 ;// *2 because of S and SM in ggml_compute_forward_flash_attn_back 3009if (node -> src [1 ]-> type == GGML_TYPE_F32 ) { 3010cur = sizeof (float )* mxDn * n_tasks ;// TODO: this can become (n_tasks-1) 3011cur += sizeof (float )* mxDn * n_tasks ;// this is overestimated by x2 3012 }else if (node -> src [1 ]-> type == GGML_TYPE_F16 ) { 3013cur = sizeof (float )* mxDn * n_tasks ;// TODO: this can become (n_tasks-1) 3014cur += sizeof (float )* mxDn * n_tasks ;// this is overestimated by x2 3015 }else if (node -> src [1 ]-> type == GGML_TYPE_BF16 ) { 3016cur = sizeof (float )* mxDn * n_tasks ;// TODO: this can become (n_tasks-1) 3017cur += sizeof (float )* mxDn * n_tasks ;// this is overestimated by x2 3018 } 3019 }break ; 3020 3021case GGML_OP_CROSS_ENTROPY_LOSS : 3022 { 3023cur = ggml_type_size (node -> type )* (n_tasks + node -> src [0 ]-> ne [0 ]* n_tasks ); 3024 }break ; 3025case GGML_OP_GATED_DELTA_NET : 3026 { 3027const int64_t S_v = node -> src [2 ]-> ne [0 ]; 3028const int64_t K = ggml_get_op_params_i32 (node ,0 ); 3029const int64_t per_thread = S_v + (K > 1 ?S_v * S_v :0 ); 3030cur = per_thread * sizeof (float )* n_tasks ; 3031 }break ; 3032case GGML_OP_COUNT : 3033 { 3034GGML_ABORT ("fatal error" ); 3035 } 3036case GGML_OP_LIGHTNING_INDEXER : 3037 { 3038// temp buffer for dequantizing lightning indexer keys 3039const int64_t ne10 = node -> src [1 ]-> ne [0 ]; 3040cur += sizeof (float )* ne10 * n_tasks ; 3041 }break ; 3042default : 3043break ; 3044 } 3045 } 3046 3047work_size = MAX (work_size ,cur ); 3048 } 3049 3050if (work_size > 0 ) { 3051work_size += CACHE_LINE_SIZE * (n_threads ); 3052 } 3053 3054cplan .threadpool = threadpool ; 3055cplan .n_threads = MIN (max_tasks ,n_threads ); 3056cplan .work_size = work_size ; 3057cplan .work_data = NULL ; 3058 3059return cplan ; 3060} 3061 3062 3063// Try to fuse the current node with subsequent nodes for better performance. 3064// Returns the number of nodes skipped by fusion (>=1), or 0 if no fusion was applied. 3065static bool ggml_cpu_disable_fusion = false;// initialized once in ggml_cpu_init(), read-only afterwards 3066 3067static int ggml_cpu_try_fuse_ops ( 3068const struct ggml_cgraph * cgraph , 3069const int node_n , 3070const struct ggml_compute_params * params , 3071const struct ggml_cplan * cplan ) { 3072 3073if (ggml_cpu_disable_fusion || cplan -> use_ref ) { 3074return 0 ; 3075 } 3076 3077struct ggml_tensor * node = cgraph -> nodes [node_n ]; 3078 3079if (node -> op == GGML_OP_RMS_NORM ) { 3080// RMS_NORM + MUL fusion 3081const enum ggml_op fuse_ops []= {GGML_OP_RMS_NORM ,GGML_OP_MUL }; 3082if (ggml_can_fuse (cgraph ,node_n ,fuse_ops ,2 )) { 3083struct ggml_tensor * mul_node = cgraph -> nodes [node_n + 1 ]; 3084const struct ggml_tensor * mul_w = (mul_node -> src [0 ]== node ) 3085 ?mul_node -> src [1 ] :mul_node -> src [0 ]; 3086if (node -> src [0 ]-> type == GGML_TYPE_F32 && 3087mul_node -> type == GGML_TYPE_F32 && 3088mul_w -> type == GGML_TYPE_F32 && 3089mul_w -> ne [0 ]== node -> ne [0 ]&& 3090mul_w -> nb [0 ]== sizeof (float )) { 3091 3092ggml_compute_forward_rms_norm_mul_fused (params ,node ,mul_node ); 3093return 1 ; 3094 } 3095 } 3096 } 3097 3098return 0 ; 3099} 3100 3101static thread_ret_t ggml_graph_compute_thread (void * data ) { 3102struct ggml_compute_state * state = (struct ggml_compute_state * )data ; 3103struct ggml_threadpool * tp = state -> threadpool ; 3104 3105const struct ggml_cgraph * cgraph = tp -> cgraph ; 3106const struct ggml_cplan * cplan = tp -> cplan ; 3107 3108#ifdef GGML_USE_CPU_RISCV64_SPACEMIT 3109ggml_backend_cpu_riscv64_spacemit_set_numa_thread_affinity (state -> ith ); 3110#else 3111set_numa_thread_affinity (state -> ith ); 3112#endif 3113 3114struct ggml_compute_params params = { 3115/*.ith =*/ state -> ith , 3116/*.nth =*/ atomic_load_explicit (& tp -> n_graph ,memory_order_relaxed )& GGML_THREADPOOL_N_THREADS_MASK , 3117/*.wsize =*/ cplan -> work_size , 3118/*.wdata =*/ cplan -> work_data , 3119/*.threadpool =*/ tp , 3120/*.use_ref =*/ cplan -> use_ref , 3121 }; 3122 3123#ifdef GGML_USE_OPENMP 3124GGML_PRINT_DEBUG ("thread #%d compute-start cplan %p\n" ,state -> ith , (const void * )cplan ); 3125#else 3126GGML_PRINT_DEBUG ("thread #%d compute-start cplan %p last-graph %d\n" ,state -> ith , (const void * )cplan ,state -> last_graph ); 3127#endif 3128 3129for (int node_n = 0 ;node_n < cgraph -> n_nodes && atomic_load_explicit (& tp -> abort ,memory_order_relaxed )!= node_n ;node_n ++ ) { 3130struct ggml_tensor * node = cgraph -> nodes [node_n ]; 3131 3132if (ggml_op_is_empty (node -> op )) { 3133// skip NOPs 3134continue ; 3135 } 3136 3137if ((node -> flags & GGML_TENSOR_FLAG_COMPUTE )== 0 ) { 3138continue ; 3139 } 3140 3141// TODO: move fused-op detection into ggml_graph_plan so fusion decisions are made once at planning time 3142// Try fused ops, fall back to normal compute 3143const int n_fused = ggml_cpu_try_fuse_ops (cgraph ,node_n ,& params ,cplan ); 3144if (n_fused > 0 ) { 3145node_n += n_fused ; 3146 }else { 3147ggml_compute_forward (& params ,node ); 3148 } 3149 3150if (state -> ith == 0 && cplan -> abort_callback && 3151cplan -> abort_callback (cplan -> abort_callback_data )) { 3152atomic_store_explicit (& tp -> abort ,node_n + 1 ,memory_order_relaxed ); 3153tp -> ec = GGML_STATUS_ABORTED ; 3154 } 3155 3156if (node_n + 1 < cgraph -> n_nodes ) { 3157ggml_barrier (state -> threadpool ); 3158 } 3159 } 3160 3161#ifdef GGML_USE_OPENMP 3162GGML_PRINT_DEBUG ("thread #%d compute-done cplan %p\n" ,state -> ith , (const void * )cplan ); 3163#else 3164GGML_PRINT_DEBUG ("thread #%d compute-done cplan %p last-graph %d\n" ,state -> ith , (const void * )cplan ,state -> last_graph ); 3165#endif 3166 3167ggml_barrier (state -> threadpool ); 3168 3169#ifdef GGML_USE_CPU_RISCV64_SPACEMIT 3170ggml_backend_cpu_riscv64_spacemit_clear_numa_thread_affinity_threaded (state -> ith ); 3171#endif 3172 3173return 0 ; 3174} 3175 3176#ifndef GGML_USE_OPENMP 3177 3178// check if thread is ready to proceed (exit from polling or sleeping) 3179// returns true if loops should exit, sets state->pending to indicate new work 3180static inline bool ggml_graph_compute_thread_ready (struct ggml_compute_state * state ) { 3181struct ggml_threadpool * threadpool = state -> threadpool ; 3182 3183if (state -> pending || threadpool -> stop || threadpool -> pause ) {return true; } 3184 3185// check for new graph/work 3186int n_graph = atomic_load_explicit (& threadpool -> n_graph ,memory_order_relaxed ); 3187int n_threads = n_graph & GGML_THREADPOOL_N_THREADS_MASK ; 3188if (n_graph != state -> last_graph ) { 3189state -> pending = (state -> ith < n_threads ); 3190state -> last_graph = n_graph ; 3191return true; 3192 } 3193 3194return false; 3195} 3196 3197// sync thread state after polling 3198static inline void ggml_graph_compute_thread_sync (struct ggml_compute_state * state ) { 3199// TSAN doesn't support standalone fence yet, we use a dummy read-modify-write instead 3200#ifdef GGML_TSAN_ENABLED 3201atomic_fetch_add_explicit (& state -> threadpool -> n_graph ,0 ,memory_order_seq_cst ); 3202#else 3203atomic_thread_fence (memory_order_seq_cst ); 3204#endif 3205UNUSED (state ); 3206} 3207 3208static inline bool ggml_graph_compute_poll_for_work (struct ggml_compute_state * state ) { 3209struct ggml_threadpool * threadpool = state -> threadpool ; 3210 3211// This seems to make 0 ... 100 a decent range for polling level across modern processors. 3212// Perhaps, we can adjust it dynamically based on load and things. 3213const uint64_t n_rounds = 1024UL * 128 * threadpool -> poll ; 3214 3215for (uint64_t i = 0 ; !ggml_graph_compute_thread_ready (state )&& i < n_rounds ;i ++ ) { 3216// No new work. Keep polling. 3217ggml_thread_cpu_relax (); 3218 } 3219 3220return state -> pending ; 3221} 3222 3223static inline bool ggml_graph_compute_check_for_work (struct ggml_compute_state * state ) { 3224struct ggml_threadpool * threadpool = state -> threadpool ; 3225 3226if (ggml_graph_compute_poll_for_work (state )) { 3227ggml_graph_compute_thread_sync (state ); 3228return state -> pending ; 3229 } 3230 3231ggml_mutex_lock_shared (& threadpool -> mutex ); 3232while (!ggml_graph_compute_thread_ready (state )) { 3233// No new work. Wait for the signal. 3234GGML_PRINT_DEBUG ("thread #%d waiting for work (sleeping)\n" ,state -> ith ); 3235ggml_cond_wait (& threadpool -> cond ,& threadpool -> mutex ); 3236 } 3237ggml_mutex_unlock_shared (& threadpool -> mutex ); 3238 3239return state -> pending ; 3240} 3241 3242static thread_ret_t ggml_graph_compute_secondary_thread (void * data ) { 3243struct ggml_compute_state * state = (struct ggml_compute_state * )data ; 3244struct ggml_threadpool * threadpool = state -> threadpool ; 3245 3246ggml_thread_apply_priority (threadpool -> prio ); 3247if (ggml_thread_cpumask_is_valid (state -> cpumask )) { 3248ggml_thread_apply_affinity (state -> cpumask ); 3249 } 3250 3251while (true) { 3252// Check if we need to sleep 3253while (threadpool -> pause ) { 3254GGML_PRINT_DEBUG ("thread #%d inside pause loop\n" ,state -> ith ); 3255ggml_mutex_lock_shared (& threadpool -> mutex ); 3256if (threadpool -> pause ) { 3257ggml_cond_wait (& threadpool -> cond ,& threadpool -> mutex ); 3258 } 3259GGML_PRINT_DEBUG ("thread #%d resuming after wait\n" ,state -> ith ); 3260ggml_mutex_unlock_shared (& threadpool -> mutex ); 3261 } 3262 3263// This needs to be checked for after the cond_wait 3264if (threadpool -> stop )break ; 3265 3266// Check if there is new work 3267// The main thread is the only one that can dispatch new work 3268 3269ggml_graph_compute_check_for_work (state ); 3270if (state -> pending ) { 3271state -> pending = false; 3272ggml_graph_compute_thread (state ); 3273 } 3274 } 3275 3276return (thread_ret_t )0 ; 3277} 3278 3279// Start processing new graph 3280static void ggml_graph_compute_kickoff (struct ggml_threadpool * threadpool ,int n_threads ) 3281{ 3282// Always take the mutex here because the worker threads are doing hybrid poll/wait 3283 3284ggml_mutex_lock (& threadpool -> mutex ); 3285 3286// Update the number of active threads and the graph count 3287int n_graph = atomic_load_explicit (& threadpool -> n_graph ,memory_order_relaxed ) >>GGML_THREADPOOL_N_THREADS_BITS ; 3288n_graph = ((n_graph + 1 ) <<GGML_THREADPOOL_N_THREADS_BITS ) | (n_threads & GGML_THREADPOOL_N_THREADS_MASK ); 3289 3290GGML_PRINT_DEBUG ("compute-kickoff: n_threads %d n_graph %d\n" ,n_threads ,n_graph ); 3291 3292// Indicate the graph is ready to be processed 3293// We need the full seq-cst fence here because of the polling threads (used in thread_sync) 3294atomic_store_explicit (& threadpool -> n_graph ,n_graph ,memory_order_seq_cst ); 3295 3296if (threadpool -> pause ) { 3297// Update main thread prio and affinity to match the threadpool settings 3298ggml_thread_apply_priority (threadpool -> prio ); 3299if (ggml_thread_cpumask_is_valid (threadpool -> workers [0 ].cpumask )) { 3300ggml_thread_apply_affinity (threadpool -> workers [0 ].cpumask ); 3301 } 3302 3303// resume does cond broadcast 3304ggml_threadpool_resume_locked (threadpool ); 3305 }else { 3306ggml_cond_broadcast (& threadpool -> cond ); 3307 } 3308 3309ggml_mutex_unlock (& threadpool -> mutex ); 3310} 3311 3312#endif // GGML_USE_OPENMP 3313 3314static struct ggml_threadpool * ggml_threadpool_new_impl ( 3315struct ggml_threadpool_params * tpp , 3316struct ggml_cgraph * cgraph , 3317struct ggml_cplan * cplan ) { 3318 3319struct ggml_threadpool * threadpool = 3320ggml_aligned_malloc (sizeof (struct ggml_threadpool )); 3321 { 3322threadpool -> cgraph = cgraph ; 3323threadpool -> cplan = cplan ; 3324threadpool -> n_graph = 0 ; 3325threadpool -> n_barrier = 0 ; 3326threadpool -> n_barrier_passed = 0 ; 3327threadpool -> current_chunk = 0 ; 3328threadpool -> stop = false; 3329threadpool -> pause = tpp -> paused ; 3330threadpool -> abort = -1 ; 3331threadpool -> workers = NULL ; 3332threadpool -> n_threads = tpp -> n_threads ; 3333threadpool -> poll = tpp -> poll ; 3334threadpool -> prio = tpp -> prio ; 3335threadpool -> ec = GGML_STATUS_SUCCESS ; 3336 } 3337 3338// Allocate and init workers state 3339const size_t workers_size = sizeof (struct ggml_compute_state )* tpp -> n_threads ; 3340struct ggml_compute_state * workers = ggml_aligned_malloc (workers_size ); 3341 3342memset (workers ,0 ,workers_size ); 3343for (int j = 0 ;j < tpp -> n_threads ;j ++ ) { 3344workers [j ].threadpool = threadpool ; 3345workers [j ].ith = j ; 3346 } 3347 3348threadpool -> workers = workers ; 3349 3350#ifdef GGML_USE_OPENMP 3351int32_t cpumask_iter = 0 ; 3352 3353// Compute CPU masks for each thread 3354for (int j = 0 ;j < tpp -> n_threads ;j ++ ) { 3355ggml_thread_cpumask_next (tpp -> cpumask ,workers [j ].cpumask ,tpp -> strict_cpu ,& cpumask_iter ); 3356 } 3357#else // GGML_USE_OPENMP 3358ggml_mutex_init (& threadpool -> mutex ); 3359ggml_cond_init (& threadpool -> cond ); 3360 3361// Spin the threads for all workers, and update CPU placements. 3362// Place the main thread last (towards the higher numbered CPU cores). 3363 3364int32_t cpumask_iter = 0 ; 3365 3366for (int j = 1 ;j < tpp -> n_threads ;j ++ ) { 3367ggml_thread_cpumask_next (tpp -> cpumask ,workers [j ].cpumask ,tpp -> strict_cpu ,& cpumask_iter ); 3368 3369int32_t rc = ggml_thread_create (& workers [j ].thrd ,NULL ,ggml_graph_compute_secondary_thread ,& workers [j ]); 3370GGML_ASSERT (rc == 0 ); 3371 } 3372 3373ggml_thread_cpumask_next (tpp -> cpumask ,workers [0 ].cpumask ,tpp -> strict_cpu ,& cpumask_iter ); 3374 3375if (!threadpool -> pause ) { 3376// Update main thread prio and affinity at the start, otherwise we'll do it in resume 3377ggml_thread_apply_priority (threadpool -> prio ); 3378if (ggml_thread_cpumask_is_valid (threadpool -> workers [0 ].cpumask )) { 3379ggml_thread_apply_affinity (threadpool -> workers [0 ].cpumask ); 3380 } 3381 } 3382#endif // GGML_USE_OPENMP 3383 3384return threadpool ; 3385} 3386 3387struct ggml_threadpool * ggml_threadpool_new (struct ggml_threadpool_params * tpp ) { 3388return ggml_threadpool_new_impl (tpp ,NULL ,NULL ); 3389} 3390 3391enum ggml_status ggml_graph_compute (struct ggml_cgraph * cgraph ,struct ggml_cplan * cplan ) { 3392ggml_cpu_init (); 3393 3394GGML_ASSERT (cplan ); 3395GGML_ASSERT (cplan -> n_threads > 0 ); 3396GGML_ASSERT (cplan -> work_size == 0 || cplan -> work_data != NULL ); 3397 3398int n_threads = cplan -> n_threads ; 3399struct ggml_threadpool * threadpool = cplan -> threadpool ; 3400 3401bool disposable_threadpool = false; 3402 3403if (threadpool == NULL ) { 3404//GGML_PRINT_DEBUG("Threadpool is not specified. Will create a disposable threadpool : n_threads %d\n", n_threads); 3405disposable_threadpool = true; 3406 3407struct ggml_threadpool_params ttp = ggml_threadpool_params_default (n_threads ); 3408threadpool = ggml_threadpool_new_impl (& ttp ,cgraph ,cplan ); 3409 }else { 3410// Reset some of the parameters that need resetting 3411// No worker threads should be accessing the parameters below at this stage 3412threadpool -> cgraph = cgraph ; 3413threadpool -> cplan = cplan ; 3414threadpool -> current_chunk = 0 ; 3415threadpool -> abort = -1 ; 3416threadpool -> ec = GGML_STATUS_SUCCESS ; 3417 } 3418 3419#ifdef GGML_USE_OPENMP 3420if (n_threads > 1 ) { 3421#pragma omp parallel num_threads(n_threads) 3422 { 3423#pragma omp single 3424 { 3425// update the number of threads from the actual number of threads that we got from OpenMP 3426n_threads = omp_get_num_threads (); 3427atomic_store_explicit (& threadpool -> n_graph ,n_threads ,memory_order_relaxed ); 3428 } 3429 3430// Apply thread CPU mask and priority 3431int ith = omp_get_thread_num (); 3432 3433ggml_thread_apply_priority (threadpool -> prio ); 3434if (ggml_thread_cpumask_is_valid (threadpool -> workers [ith ].cpumask )) { 3435ggml_thread_apply_affinity (threadpool -> workers [ith ].cpumask ); 3436 } 3437ggml_graph_compute_thread (& threadpool -> workers [ith ]); 3438 } 3439 }else { 3440atomic_store_explicit (& threadpool -> n_graph ,1 ,memory_order_relaxed ); 3441ggml_graph_compute_thread (& threadpool -> workers [0 ]); 3442 } 3443#else 3444if (n_threads > threadpool -> n_threads ) { 3445GGML_LOG_WARN ("cplan requested more threads (%d) than available (%d)\n" ,n_threads ,threadpool -> n_threads ); 3446n_threads = threadpool -> n_threads ; 3447 } 3448 3449// Kick all threads to start the new graph 3450ggml_graph_compute_kickoff (threadpool ,n_threads ); 3451 3452// This is a work thread too 3453ggml_graph_compute_thread (& threadpool -> workers [0 ]); 3454#endif 3455 3456// don't leave affinity set on the main thread 3457clear_numa_thread_affinity (); 3458 3459enum ggml_status ret = threadpool -> ec ; 3460 3461if (disposable_threadpool ) { 3462ggml_threadpool_free (threadpool ); 3463 } 3464 3465return ret ; 3466} 3467 3468enum ggml_status ggml_graph_compute_with_ctx (struct ggml_context * ctx ,struct ggml_cgraph * cgraph ,int n_threads ) { 3469struct ggml_cplan cplan = ggml_graph_plan (cgraph ,n_threads ,NULL ); 3470 3471cplan .work_data = (uint8_t * )ggml_new_buffer (ctx ,cplan .work_size ); 3472 3473return ggml_graph_compute (cgraph ,& cplan ); 3474} 3475 3476void ggml_cpu_fp32_to_fp32 (const float * x ,float * y ,int64_t n ) { 3477memcpy (y ,x ,n * sizeof (float )); 3478} 3479 3480void ggml_cpu_fp32_to_fp16 (const float * x ,ggml_fp16_t * y ,int64_t n ) { 3481int64_t i = 0 ; 3482#if defined(__F16C__ ) 3483#if defined(__AVX512F__ ) 3484for (;i + 15 < n ;i += 16 ) { 3485__m512 x_vec = _mm512_loadu_ps (x + i ); 3486__m256i y_vec = _mm512_cvtps_ph (x_vec ,_MM_FROUND_TO_NEAREST_INT ); 3487_mm256_storeu_si256 ((__m256i * )(y + i ),y_vec ); 3488 } 3489#endif 3490for (;i + 7 < n ;i += 8 ) { 3491__m256 x_vec = _mm256_loadu_ps (x + i ); 3492__m128i y_vec = _mm256_cvtps_ph (x_vec ,_MM_FROUND_TO_NEAREST_INT ); 3493_mm_storeu_si128 ((__m128i * )(y + i ),y_vec ); 3494 } 3495for (;i + 3 < n ;i += 4 ) { 3496__m128 x_vec = _mm_loadu_ps (x + i ); 3497__m128i y_vec = _mm_cvtps_ph (x_vec ,_MM_FROUND_TO_NEAREST_INT ); 3498_mm_storel_epi64 ((__m128i * )(y + i ),y_vec ); 3499 } 3500#elif defined(__riscv_zvfh ) 3501for (int vl ;i < n ;i += vl ) { 3502vl = __riscv_vsetvl_e32m2 (n - i ); 3503vfloat32m2_t vx = __riscv_vle32_v_f32m2 (& x [i ],vl ); 3504vfloat16m1_t vy = __riscv_vfncvt_f_f_w_f16m1 (vx ,vl ); 3505__riscv_vse16_v_f16m1 ((_Float16 * )& y [i ],vy ,vl ); 3506 } 3507#endif 3508for (;i < n ;++ i ) { 3509y [i ]= GGML_CPU_FP32_TO_FP16 (x [i ]); 3510 } 3511} 3512 3513void ggml_cpu_fp16_to_fp32 (const ggml_fp16_t * x ,float * y ,int64_t n ) { 3514int64_t i = 0 ; 3515#if defined(__F16C__ ) 3516#if defined(__AVX512F__ ) 3517for (;i + 15 < n ;i += 16 ) { 3518__m256i x_vec = _mm256_loadu_si256 ((const __m256i * )(x + i )); 3519__m512 y_vec = _mm512_cvtph_ps (x_vec ); 3520_mm512_storeu_ps (y + i ,y_vec ); 3521 } 3522#endif 3523for (;i + 7 < n ;i += 8 ) { 3524__m128i x_vec = _mm_loadu_si128 ((const __m128i * )(x + i )); 3525__m256 y_vec = _mm256_cvtph_ps (x_vec ); 3526_mm256_storeu_ps (y + i ,y_vec ); 3527 } 3528for (;i + 3 < n ;i += 4 ) { 3529__m128i x_vec = _mm_loadl_epi64 ((const __m128i * )(x + i )); 3530__m128 y_vec = _mm_cvtph_ps (x_vec ); 3531_mm_storeu_ps (y + i ,y_vec ); 3532 } 3533 3534#elif defined(__riscv_v_intrinsic )&& defined(__riscv_zvfhmin ) 3535// calculate step size 3536const int epr = __riscv_vsetvlmax_e16m2 (); 3537const int step = epr * 2 ; 3538const int np = (n & ~(step - 1 )); 3539 3540// unroll by 2 3541for (;i < np ;i += step ) { 3542vfloat16m2_t ax0 = __riscv_vle16_v_f16m2 ((const _Float16 * )x + i ,epr ); 3543vfloat32m4_t ay0 = __riscv_vfwcvt_f_f_v_f32m4 (ax0 ,epr ); 3544__riscv_vse32_v_f32m4 (y + i ,ay0 ,epr ); 3545 3546vfloat16m2_t ax1 = __riscv_vle16_v_f16m2 ((const _Float16 * )x + i + epr ,epr ); 3547vfloat32m4_t ay1 = __riscv_vfwcvt_f_f_v_f32m4 (ax1 ,epr ); 3548__riscv_vse32_v_f32m4 (y + i + epr ,ay1 ,epr ); 3549 } 3550 3551// leftovers 3552int vl ; 3553for (i = np ;i < n ;i += vl ) { 3554vl = __riscv_vsetvl_e16m2 (n - i ); 3555vfloat16m2_t ax0 = __riscv_vle16_v_f16m2 ((const _Float16 * )x + i ,vl ); 3556vfloat32m4_t ay0 = __riscv_vfwcvt_f_f_v_f32m4 (ax0 ,vl ); 3557__riscv_vse32_v_f32m4 (y + i ,ay0 ,vl ); 3558 } 3559 3560#endif 3561 3562for (;i < n ;++ i ) { 3563y [i ]= GGML_CPU_FP16_TO_FP32 (x [i ]); 3564 } 3565} 3566 3567void ggml_cpu_fp32_to_bf16 (const float * x ,ggml_bf16_t * y ,int64_t n ) { 3568int64_t i = 0 ; 3569for (;i < n ;++ i ) { 3570y [i ]= GGML_FP32_TO_BF16 (x [i ]); 3571 } 3572} 3573 3574void ggml_cpu_fp32_to_i32 (const float * x ,int32_t * y ,int64_t n ) { 3575int64_t i = 0 ; 3576for (;i < n ;++ i ) { 3577y [i ]= x [i ]; 3578 } 3579} 3580 3581void ggml_cpu_bf16_to_fp32 (const ggml_bf16_t * x ,float * y ,int64_t n ) { 3582int64_t i = 0 ; 3583#if defined(__AVX2__ ) 3584#if defined(__AVX512F__ ) 3585for (;i + 15 < n ;i += 16 ) { 3586_mm512_storeu_ps (y + i , 3587_mm512_castsi512_ps ( 3588_mm512_slli_epi32 ( 3589_mm512_cvtepu16_epi32 ( 3590_mm256_loadu_si256 ( 3591 (const __m256i * )(x + i ))), 359216 ))); 3593 } 3594#endif 3595for (;i + 7 < n ;i += 8 ) { 3596_mm256_storeu_ps (y + i , 3597_mm256_castsi256_ps ( 3598_mm256_slli_epi32 ( 3599_mm256_cvtepu16_epi32 ( 3600_mm_loadu_si128 ( 3601 (const __m128i * )(x + i ))), 360216 ))); 3603 } 3604#elif defined(__riscv_v_intrinsic )&& defined(__riscv_zvfbfmin ) 3605// calculate step size 3606const int epr = __riscv_vsetvlmax_e16m2 (); 3607const int step = epr * 2 ; 3608const int np = (n & ~(step - 1 )); 3609 3610// unroll by 2 3611for (;i < np ;i += step ) { 3612vbfloat16m2_t ax0 = __riscv_vle16_v_bf16m2 ((const __bf16 * )x + i ,epr ); 3613vfloat32m4_t ay0 = __riscv_vfwcvtbf16_f_f_v_f32m4 (ax0 ,epr ); 3614__riscv_vse32_v_f32m4 (y + i ,ay0 ,epr ); 3615 3616vbfloat16m2_t ax1 = __riscv_vle16_v_bf16m2 ((const __bf16 * )x + i + epr ,epr ); 3617vfloat32m4_t ay1 = __riscv_vfwcvtbf16_f_f_v_f32m4 (ax1 ,epr ); 3618__riscv_vse32_v_f32m4 (y + i + epr ,ay1 ,epr ); 3619 } 3620 3621// leftovers 3622int vl ; 3623for (i = np ;i < n ;i += vl ) { 3624vl = __riscv_vsetvl_e16m2 (n - i ); 3625vbfloat16m2_t ax0 = __riscv_vle16_v_bf16m2 ((const __bf16 * )x + i ,vl ); 3626vfloat32m4_t ay0 = __riscv_vfwcvtbf16_f_f_v_f32m4 (ax0 ,vl ); 3627__riscv_vse32_v_f32m4 (y + i ,ay0 ,vl ); 3628 } 3629#endif 3630for (;i < n ;i ++ ) { 3631y [i ]= GGML_BF16_TO_FP32 (x [i ]); 3632 } 3633} 3634 3635int ggml_cpu_has_avx (void ) { 3636#if defined(__AVX__ ) 3637return 1 ; 3638#else 3639return 0 ; 3640#endif 3641} 3642 3643int ggml_cpu_has_avx_vnni (void ) { 3644#if defined(__AVXVNNI__ ) 3645return 1 ; 3646#else 3647return 0 ; 3648#endif 3649} 3650 3651int ggml_cpu_has_avx2 (void ) { 3652#if defined(__AVX2__ ) 3653return 1 ; 3654#else 3655return 0 ; 3656#endif 3657} 3658 3659int ggml_cpu_has_avx512 (void ) { 3660#if defined(__AVX512F__ ) 3661return 1 ; 3662#else 3663return 0 ; 3664#endif 3665} 3666 3667int ggml_cpu_has_avx512_vbmi (void ) { 3668#if defined(__AVX512VBMI__ ) 3669return 1 ; 3670#else 3671return 0 ; 3672#endif 3673} 3674 3675int ggml_cpu_has_avx512_vnni (void ) { 3676#if defined(__AVX512VNNI__ ) 3677return 1 ; 3678#else 3679return 0 ; 3680#endif 3681} 3682 3683int ggml_cpu_has_avx512_bf16 (void ) { 3684#if defined(__AVX512BF16__ ) 3685return 1 ; 3686#else 3687return 0 ; 3688#endif 3689} 3690 3691int ggml_cpu_has_amx_int8 (void ) { 3692#if defined(__AMX_INT8__ ) 3693return 1 ; 3694#else 3695return 0 ; 3696#endif 3697} 3698 3699int ggml_cpu_has_bmi2 (void ) { 3700#if defined(__BMI2__ ) 3701return 1 ; 3702#else 3703return 0 ; 3704#endif 3705} 3706 3707int ggml_cpu_has_fma (void ) { 3708#if defined(__FMA__ ) 3709return 1 ; 3710#else 3711return 0 ; 3712#endif 3713} 3714 3715int ggml_cpu_has_arm_fma (void ) { 3716#if defined(__ARM_FEATURE_FMA ) 3717return 1 ; 3718#else 3719return 0 ; 3720#endif 3721} 3722 3723int ggml_cpu_has_riscv_v (void ) { 3724#if defined(__riscv_v_intrinsic ) 3725return 1 ; 3726#else 3727return 0 ; 3728#endif 3729} 3730 3731int ggml_cpu_get_rvv_vlen (void ) { 3732#if defined(__riscv )&& defined(__riscv_v_intrinsic ) 3733return ggml_riscv_arch_features .rvv_vlen ; 3734#else 3735return 0 ; 3736#endif 3737} 3738 3739int ggml_cpu_has_f16c (void ) { 3740#if defined(__F16C__ ) 3741return 1 ; 3742#else 3743return 0 ; 3744#endif 3745} 3746 3747int ggml_cpu_has_fp16_va (void ) { 3748#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC ) 3749return 1 ; 3750#else 3751return 0 ; 3752#endif 3753} 3754 3755int ggml_cpu_has_wasm_simd (void ) { 3756#if defined(__wasm_simd128__ ) 3757return 1 ; 3758#else 3759return 0 ; 3760#endif 3761} 3762 3763int ggml_cpu_has_llamafile (void ) { 3764#if defined(GGML_USE_LLAMAFILE ) 3765return 1 ; 3766#else 3767return 0 ; 3768#endif 3769} 3770 3771int ggml_cpu_has_sse3 (void ) { 3772#if defined(__SSE3__ ) 3773return 1 ; 3774#else 3775return 0 ; 3776#endif 3777} 3778 3779int ggml_cpu_has_ssse3 (void ) { 3780#if defined(__SSSE3__ ) 3781return 1 ; 3782#else 3783return 0 ; 3784#endif 3785} 3786 3787int ggml_cpu_has_vsx (void ) { 3788#if defined(__POWER9_VECTOR__ ) 3789return 1 ; 3790#else 3791return 0 ; 3792#endif 3793} 3794 3795int ggml_cpu_has_vxe (void ) { 3796#if defined(__VXE__ )|| defined(__VXE2__ ) 3797return 1 ; 3798#else 3799return 0 ; 3800#endif 3801} 3802 3803int ggml_cpu_has_neon (void ) { 3804#if defined(__ARM_ARCH )&& defined(__ARM_NEON ) 3805return 1 ; 3806#else 3807return 0 ; 3808#endif 3809} 3810 3811int ggml_cpu_has_dotprod (void ) { 3812#if defined(__ARM_ARCH )&& defined(__ARM_FEATURE_DOTPROD ) 3813return 1 ; 3814#else 3815return 0 ; 3816#endif 3817} 3818 3819int ggml_cpu_has_sve (void ) { 3820#if defined(__ARM_ARCH )&& defined(__ARM_FEATURE_SVE ) 3821return 1 ; 3822#else 3823return 0 ; 3824#endif 3825} 3826 3827int ggml_cpu_has_matmul_int8 (void ) { 3828#if defined(__ARM_ARCH )&& defined(__ARM_FEATURE_MATMUL_INT8 ) 3829return 1 ; 3830#else 3831return 0 ; 3832#endif 3833} 3834 3835int ggml_cpu_get_sve_cnt (void ) { 3836#if defined(__ARM_ARCH )&& defined(__ARM_FEATURE_SVE ) 3837return ggml_arm_arch_features .sve_cnt ; 3838#else 3839return 0 ; 3840#endif 3841} 3842 3843int ggml_cpu_has_sme (void ) { 3844#if defined(__ARM_ARCH )&& defined(__ARM_FEATURE_SME ) 3845return 1 ; 3846#else 3847return 0 ; 3848#endif 3849} 3850 3851int ggml_cpu_has_sme2 (void ) { 3852#if defined(__ARM_ARCH )&& defined(__ARM_FEATURE_SME2 ) 3853return 1 ; 3854#else 3855return 0 ; 3856#endif 3857} 3858 3859void ggml_cpu_init (void ) { 3860// needed to initialize ggml_time 3861 { 3862struct ggml_init_params params = {0 ,NULL , false }; 3863struct ggml_context * ctx = ggml_init (params ); 3864ggml_free (ctx ); 3865 } 3866 3867ggml_critical_section_start (); 3868 3869static bool is_first_call = true; 3870 3871if (is_first_call ) { 3872// initialize GELU, Quick GELU, SILU and EXP F32 tables 3873 { 3874const uint64_t t_start = ggml_time_us ();UNUSED (t_start ); 3875 3876for (int i = 0 ;i < (1 <<16 );++ i ) { 3877union { 3878uint16_t u16 ; 3879ggml_fp16_t fp16 ; 3880 }u = {i }; 3881float f = GGML_COMPUTE_FP16_TO_FP32 (u .fp16 ); 3882ggml_table_f32_f16 [i ]= f ; 3883ggml_table_gelu_f16 [i ]= GGML_CPU_FP32_TO_FP16 (ggml_gelu_f32 (f )); 3884ggml_table_gelu_quick_f16 [i ]= GGML_CPU_FP32_TO_FP16 (ggml_gelu_quick_f32 (f )); 3885 } 3886 3887// initialize E8M0 half table (256 entries) 3888for (int i = 0 ;i < (1 <<8 );++ i ) { 3889ggml_table_f32_e8m0_half [i ]= GGML_E8M0_TO_FP32_HALF (i ); 3890 } 3891 3892// initialize UE4M3 table (256 entries) 3893for (int i = 0 ;i < (1 <<8 );++ i ) { 3894ggml_table_f32_ue4m3 [i ]= ggml_ue4m3_to_fp32 (i ); 3895 } 3896 3897const uint64_t t_end = ggml_time_us ();UNUSED (t_end ); 3898 3899GGML_PRINT_DEBUG ("%s: GELU, Quick GELU, SILU and EXP tables initialized in %f ms\n" ,__func__ , (t_end - t_start )/1000.0 ); 3900 3901#ifdef GGML_USE_OPENMP 3902//if (!getenv("OMP_WAIT_POLICY")) { 3903// // set the wait policy to active, so that OpenMP threads don't sleep 3904// setenv("OMP_WAIT_POLICY", "active", 0) 3905//} 3906 3907if (!getenv ("KMP_BLOCKTIME" )) { 3908// set the time to wait before sleeping a thread 3909// this is less aggressive than setting the wait policy to active, but should achieve similar results in most cases 3910#ifdef _WIN32 3911_putenv_s ("KMP_BLOCKTIME" ,"200" );// 200ms 3912#else 3913setenv ("KMP_BLOCKTIME" ,"200" ,0 );// 200ms 3914#endif 3915 } 3916#endif 3917 } 3918 3919#if defined(__ARM_ARCH ) 3920ggml_init_arm_arch_features (); 3921#endif 3922 3923#if defined(__riscv ) 3924ggml_init_riscv_arch_features (); 3925#endif 3926 3927 { 3928const char * env = getenv ("GGML_CPU_DISABLE_FUSION" ); 3929ggml_cpu_disable_fusion = (env != NULL && atoi (env )== 1 ); 3930 } 3931 3932is_first_call = false; 3933 } 3934 3935ggml_critical_section_end (); 3936}