char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
1692f9e50
char/aliceai-t5-moe
1#include "ggml-backend.h" 2#include "ggml-backend-impl.h" 3#include "ggml-cpu.h" 4#include "repack.h" 5#include "traits.h" 6#include "ggml-impl.h" 7#include "amx/amx.h" 8 9#include <cctype> 10#include <string> 11#include <vector> 12 13#ifdef GGML_USE_CPU_HBM 14# include "hbm.h" 15#endif 16 17#ifdef GGML_USE_CPU_KLEIDIAI 18# include "kleidiai/kleidiai.h" 19#endif 20 21#ifdef GGML_USE_CPU_RISCV64_SPACEMIT 22# include "spacemit/ime.h" 23#endif 24 25#if defined(_WIN32 ) 26# define WIN32_LEAN_AND_MEAN 27# ifndef NOMINMAX 28# define NOMINMAX 29# endif 30# include <windows.h> 31#else 32# include <unistd.h> 33#endif 34 35#if defined(__APPLE__ ) 36# include <sys/sysctl.h> 37# include <sys/types.h> 38#endif 39 40// ggml-backend interface 41 42std::vector < ggml_backend_buffer_type_t > & ggml_backend_cpu_get_extra_buffer_types () { 43static std::vector < ggml_backend_buffer_type_t > bufts = []() { 44 std::vector < ggml_backend_buffer_type_t > bufts ; 45 46#if defined(__AMX_INT8__ )&& defined(__AVX512VNNI__ ) 47if (ggml_backend_amx_buffer_type ()) { 48bufts .push_back (ggml_backend_amx_buffer_type ()); 49 } 50#endif 51 52#ifdef GGML_USE_CPU_RISCV64_SPACEMIT 53if (ggml_backend_cpu_riscv64_spacemit_buffer_type ()) { 54bufts .push_back (ggml_backend_cpu_riscv64_spacemit_buffer_type ()); 55 } 56#endif 57 58#ifdef GGML_USE_CPU_KLEIDIAI 59if (ggml_backend_cpu_kleidiai_buffer_type ()) { 60bufts .push_back (ggml_backend_cpu_kleidiai_buffer_type ()); 61 } 62#endif 63 64#ifdef GGML_USE_CPU_REPACK 65if (ggml_backend_cpu_repack_buffer_type ()) { 66bufts .push_back (ggml_backend_cpu_repack_buffer_type ()); 67 } 68#endif 69 70return bufts ; 71 }(); 72 73return bufts ; 74} 75 76static ggml_backend_buffer_type_t * ggml_backend_cpu_device_get_extra_buffers_type (ggml_backend_dev_t device ) { 77static std::vector < ggml_backend_buffer_type_t > extra_bufts = [] { 78 std::vector < ggml_backend_buffer_type_t > bufts = ggml_backend_cpu_get_extra_buffer_types (); 79bufts .push_back (nullptr ); 80return bufts ; 81 }(); 82 83return extra_bufts .data (); 84 85GGML_UNUSED (device ); 86} 87 88static bool ggml_backend_cpu_is_extra_buffer_type (ggml_backend_buffer_type_t buft ) { 89for (auto * extra :ggml_backend_cpu_get_extra_buffer_types ()) { 90if (extra == buft ) { 91return true; 92 } 93 } 94return false; 95} 96 97// CPU backend - backend (stream) 98 99struct ggml_backend_cpu_context { 100int n_threads ; 101ggml_threadpool_t threadpool ; 102 103uint8_t * work_data ; 104size_t work_size ; 105 106ggml_abort_callback abort_callback ; 107void * abort_callback_data ; 108 109bool use_ref ;// use reference implementation 110}; 111 112static const char * ggml_backend_cpu_get_name (ggml_backend_t backend ) { 113return "CPU" ; 114 115GGML_UNUSED (backend ); 116} 117 118static void ggml_backend_cpu_free (ggml_backend_t backend ) { 119struct ggml_backend_cpu_context * cpu_ctx = (struct ggml_backend_cpu_context * )backend -> context ; 120delete []cpu_ctx -> work_data ; 121delete cpu_ctx ; 122delete backend ; 123} 124 125struct ggml_backend_plan_cpu { 126struct ggml_cplan cplan ; 127struct ggml_cgraph cgraph ; 128}; 129 130static ggml_backend_graph_plan_t ggml_backend_cpu_graph_plan_create (ggml_backend_t backend ,const struct ggml_cgraph * cgraph ) { 131struct ggml_backend_cpu_context * cpu_ctx = (struct ggml_backend_cpu_context * )backend -> context ; 132 133struct ggml_backend_plan_cpu * cpu_plan = new ggml_backend_plan_cpu ; 134 135cpu_plan -> cplan = ggml_graph_plan (cgraph ,cpu_ctx -> n_threads ,cpu_ctx -> threadpool ); 136cpu_plan -> cgraph = * cgraph ;// FIXME: deep copy 137 138if (cpu_plan -> cplan .work_size > 0 ) { 139cpu_plan -> cplan .work_data = new uint8_t [cpu_plan -> cplan .work_size ]; 140if (cpu_plan -> cplan .work_data == NULL ) { 141delete cpu_plan ; 142return NULL ; 143 } 144 } 145 146cpu_plan -> cplan .abort_callback = cpu_ctx -> abort_callback ; 147cpu_plan -> cplan .abort_callback_data = cpu_ctx -> abort_callback_data ; 148cpu_plan -> cplan .use_ref = cpu_ctx -> use_ref ; 149 150return cpu_plan ; 151} 152 153static void ggml_backend_cpu_graph_plan_free (ggml_backend_t backend ,ggml_backend_graph_plan_t plan ) { 154struct ggml_backend_plan_cpu * cpu_plan = (struct ggml_backend_plan_cpu * )plan ; 155 156delete []cpu_plan -> cplan .work_data ; 157delete cpu_plan ; 158 159GGML_UNUSED (backend ); 160} 161 162static enum ggml_status ggml_backend_cpu_graph_plan_compute (ggml_backend_t backend ,ggml_backend_graph_plan_t plan ) { 163struct ggml_backend_plan_cpu * cpu_plan = (struct ggml_backend_plan_cpu * )plan ; 164 165return ggml_graph_compute (& cpu_plan -> cgraph ,& cpu_plan -> cplan ); 166 167GGML_UNUSED (backend ); 168} 169 170static enum ggml_status ggml_backend_cpu_graph_compute (ggml_backend_t backend ,struct ggml_cgraph * cgraph ) { 171struct ggml_backend_cpu_context * cpu_ctx = (struct ggml_backend_cpu_context * )backend -> context ; 172 173struct ggml_cplan cplan = ggml_graph_plan (cgraph ,cpu_ctx -> n_threads ,cpu_ctx -> threadpool ); 174 175if (cpu_ctx -> work_size < cplan .work_size ) { 176delete []cpu_ctx -> work_data ; 177cpu_ctx -> work_data = new uint8_t [cplan .work_size ]; 178if (cpu_ctx -> work_data == NULL ) { 179cpu_ctx -> work_size = 0 ; 180return GGML_STATUS_ALLOC_FAILED ; 181 } 182cpu_ctx -> work_size = cplan .work_size ; 183 } 184cplan .work_data = (uint8_t * )cpu_ctx -> work_data ; 185 186cplan .abort_callback = cpu_ctx -> abort_callback ; 187cplan .abort_callback_data = cpu_ctx -> abort_callback_data ; 188cplan .use_ref = cpu_ctx -> use_ref ; 189 190return ggml_graph_compute (cgraph ,& cplan ); 191} 192 193static const struct ggml_backend_i ggml_backend_cpu_i = { 194/* .get_name = */ ggml_backend_cpu_get_name , 195/* .free = */ ggml_backend_cpu_free , 196/* .set_tensor_async = */ NULL , 197/* .get_tensor_async = */ NULL , 198/* .set_tensor_2d_async = */ NULL , 199/* .get_tensor_2d_async = */ NULL , 200/* .cpy_tensor_async = */ NULL , 201/* .synchronize = */ NULL , 202/* .graph_plan_create = */ ggml_backend_cpu_graph_plan_create , 203/* .graph_plan_free = */ ggml_backend_cpu_graph_plan_free , 204/* .graph_plan_update = */ NULL , 205/* .graph_plan_compute = */ ggml_backend_cpu_graph_plan_compute , 206/* .graph_compute = */ ggml_backend_cpu_graph_compute , 207/* .event_record = */ NULL , 208/* .event_wait = */ NULL , 209/* .graph_optimize = */ NULL , 210}; 211 212static ggml_guid_t ggml_backend_cpu_guid (void ) { 213static ggml_guid guid = {0xaa ,0x67 ,0xc7 ,0x43 ,0x96 ,0xe6 ,0xa3 ,0x8a ,0xe3 ,0xaf ,0xea ,0x92 ,0x36 ,0xbc ,0xfc ,0x89 }; 214return & guid ; 215} 216 217ggml_backend_t ggml_backend_cpu_init (void ) { 218// initialize CPU backend now to avoid slowing the first graph computation 219ggml_cpu_init (); 220 221struct ggml_backend_cpu_context * ctx = new ggml_backend_cpu_context ; 222if (ctx == NULL ) { 223return NULL ; 224 } 225 226ctx -> n_threads = GGML_DEFAULT_N_THREADS ; 227ctx -> threadpool = NULL ; 228ctx -> work_data = NULL ; 229ctx -> work_size = 0 ; 230ctx -> abort_callback = NULL ; 231ctx -> abort_callback_data = NULL ; 232ctx -> use_ref = false; 233 234ggml_backend_t cpu_backend = new ggml_backend { 235/* .guid = */ ggml_backend_cpu_guid (), 236/* .iface = */ ggml_backend_cpu_i , 237/* .device = */ ggml_backend_reg_dev_get (ggml_backend_cpu_reg (),0 ), 238/* .context = */ ctx , 239 }; 240 241if (cpu_backend == NULL ) { 242delete ctx ; 243return NULL ; 244 } 245 246return cpu_backend ; 247} 248 249bool ggml_backend_is_cpu (ggml_backend_t backend ) { 250return backend != NULL && ggml_guid_matches (backend -> guid ,ggml_backend_cpu_guid ()); 251} 252 253void ggml_backend_cpu_set_n_threads (ggml_backend_t backend_cpu ,int n_threads ) { 254GGML_ASSERT (ggml_backend_is_cpu (backend_cpu )); 255 256struct ggml_backend_cpu_context * ctx = (struct ggml_backend_cpu_context * )backend_cpu -> context ; 257ctx -> n_threads = n_threads ; 258} 259 260void ggml_backend_cpu_set_threadpool (ggml_backend_t backend_cpu ,ggml_threadpool_t threadpool ) { 261GGML_ASSERT (ggml_backend_is_cpu (backend_cpu )); 262 263struct ggml_backend_cpu_context * ctx = (struct ggml_backend_cpu_context * )backend_cpu -> context ; 264 265if (ctx -> threadpool && ctx -> threadpool != threadpool ) { 266// already had a different threadpool, pause/suspend it before switching 267ggml_threadpool_pause (ctx -> threadpool ); 268 } 269ctx -> threadpool = threadpool ; 270} 271 272void ggml_backend_cpu_set_abort_callback (ggml_backend_t backend_cpu ,ggml_abort_callback abort_callback ,void * abort_callback_data ) { 273GGML_ASSERT (ggml_backend_is_cpu (backend_cpu )); 274 275struct ggml_backend_cpu_context * ctx = (struct ggml_backend_cpu_context * )backend_cpu -> context ; 276ctx -> abort_callback = abort_callback ; 277ctx -> abort_callback_data = abort_callback_data ; 278} 279 280void ggml_backend_cpu_set_use_ref (ggml_backend_t backend_cpu ,bool use_ref ) { 281GGML_ASSERT (ggml_backend_is_cpu (backend_cpu )); 282 283struct ggml_backend_cpu_context * ctx = (struct ggml_backend_cpu_context * )backend_cpu -> context ; 284ctx -> use_ref = use_ref ; 285} 286 287// CPU backend - device 288 289struct ggml_backend_cpu_device_context { 290 std::string description = "CPU" ; 291 292ggml_backend_cpu_device_context () { 293#ifdef __APPLE__ 294size_t len = 0 ; 295if (!sysctlbyname ("machdep.cpu.brand_string" ,NULL ,& len ,NULL ,0 )) { 296description .resize (len ); 297sysctlbyname ("machdep.cpu.brand_string" ,& description [0 ],& len ,NULL ,0 );// NOLINT 298 } 299#elif defined(__linux__ ) 300FILE * f = fopen ("/proc/cpuinfo" ,"r" ); 301if (f ) { 302char buf [1024 ]; 303while (fgets (buf ,sizeof (buf ),f )) { 304if (strncmp (buf ,"model name" ,10 )== 0 ) { 305char * p = strchr (buf ,':' ); 306if (p ) { 307p ++ ; 308while (std::isspace (* p )) { 309p ++ ; 310 } 311while (std::isspace (p [strlen (p )- 1 ])) { 312p [strlen (p )- 1 ]= '\0' ; 313 } 314description = p ; 315break ; 316 } 317 } 318 } 319fclose (f ); 320 } 321#elif defined(_WIN32 ) 322HKEY hKey ; 323if (RegOpenKeyEx (HKEY_LOCAL_MACHINE , 324TEXT ("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0" ), 3250 , 326KEY_READ , 327& hKey )== ERROR_SUCCESS ) { 328DWORD cpu_brand_size = 0 ; 329if (RegQueryValueExA (hKey , 330"ProcessorNameString" , 331NULL , 332NULL , 333NULL , 334& cpu_brand_size )== ERROR_SUCCESS ) { 335description .resize (cpu_brand_size ); 336if (RegQueryValueExA (hKey , 337"ProcessorNameString" , 338NULL , 339NULL , 340 (LPBYTE )& description [0 ],// NOLINT 341& cpu_brand_size )== ERROR_SUCCESS ) { 342if (description .find ('\0' )!= std::string::npos ) { 343description .resize (description .find ('\0' )); 344 } 345 } 346 } 347RegCloseKey (hKey ); 348 } 349#endif 350 } 351}; 352 353static const char * ggml_backend_cpu_device_get_name (ggml_backend_dev_t dev ) { 354return "CPU" ; 355 356GGML_UNUSED (dev ); 357} 358 359static const char * ggml_backend_cpu_device_get_description (ggml_backend_dev_t dev ) { 360struct ggml_backend_cpu_device_context * ctx = (struct ggml_backend_cpu_device_context * )dev -> context ; 361 362return ctx -> description .c_str (); 363} 364 365static void ggml_backend_cpu_device_get_memory (ggml_backend_dev_t dev ,size_t * free ,size_t * total ) { 366#ifdef _WIN32 367MEMORYSTATUSEX status ; 368status .dwLength = sizeof (status ); 369GlobalMemoryStatusEx (& status ); 370* total = status .ullTotalPhys ; 371* free = status .ullAvailPhys ; 372#else 373long pages = sysconf (_SC_PHYS_PAGES ); 374long page_size = sysconf (_SC_PAGE_SIZE ); 375* total = pages * page_size ; 376 377// "free" system memory is ill-defined, for practical purposes assume that all of it is free: 378* free = * total ; 379#endif // _WIN32 380 381GGML_UNUSED (dev ); 382} 383 384static enum ggml_backend_dev_type ggml_backend_cpu_device_get_type (ggml_backend_dev_t dev ) { 385return GGML_BACKEND_DEVICE_TYPE_CPU ; 386 387GGML_UNUSED (dev ); 388} 389 390static void ggml_backend_cpu_device_get_props (ggml_backend_dev_t dev ,struct ggml_backend_dev_props * props ) { 391props -> name = ggml_backend_cpu_device_get_name (dev ); 392props -> description = ggml_backend_cpu_device_get_description (dev ); 393props -> type = ggml_backend_cpu_device_get_type (dev ); 394ggml_backend_cpu_device_get_memory (dev ,& props -> memory_free ,& props -> memory_total ); 395props -> caps = { 396/* .async = */ false, 397/* .host_buffer = */ false, 398/* .buffer_from_host_ptr = */ true, 399/* .events = */ false, 400/* .mmap_support = */ true, 401 }; 402} 403 404static ggml_backend_t ggml_backend_cpu_device_init_backend (ggml_backend_dev_t dev ,const char * params ) { 405return ggml_backend_cpu_init (); 406 407GGML_UNUSED (dev ); 408GGML_UNUSED (params ); 409} 410 411static ggml_backend_buffer_type_t ggml_backend_cpu_device_get_buffer_type (ggml_backend_dev_t dev ) { 412return ggml_backend_cpu_buffer_type (); 413 414GGML_UNUSED (dev ); 415} 416 417static ggml_backend_buffer_t ggml_backend_cpu_device_buffer_from_host_ptr (ggml_backend_dev_t dev ,void * ptr ,size_t size ,size_t max_tensor_size ) { 418return ggml_backend_cpu_buffer_from_ptr (ptr ,size ); 419 420GGML_UNUSED (dev ); 421GGML_UNUSED (max_tensor_size ); 422} 423 424static bool ggml_backend_cpu_device_supports_op (ggml_backend_dev_t dev ,const struct ggml_tensor * op ) { 425const struct ggml_tensor * src0 = op -> src [0 ]; 426const struct ggml_tensor * src1 = op -> src [1 ]; 427 428if (op -> op == GGML_OP_NONE || op -> op == GGML_OP_RESHAPE || op -> op == GGML_OP_VIEW || op -> op == GGML_OP_PERMUTE || op -> op == GGML_OP_TRANSPOSE ) { 429return true; 430 } 431 432// check extra buffer types 433// note: only the first sources are checked for extra buffer types to reduce overhead, increase if necessary 434for (int i = 0 ;i < 4 ;i ++ ) { 435if (op -> src [i ]&& op -> src [i ]-> buffer && 436ggml_backend_cpu_is_extra_buffer_type (op -> src [i ]-> buffer -> buft )) { 437auto * buf_extra = (ggml::cpu::extra_buffer_type * )op -> src [i ]-> buffer -> buft -> context ; 438return buf_extra -> supports_op (dev ,op ); 439 } 440 } 441 442switch (op -> op ) { 443case GGML_OP_CPY : 444case GGML_OP_SET_ROWS : 445return 446op -> type != GGML_TYPE_IQ3_XXS && 447op -> type != GGML_TYPE_IQ3_S && 448op -> type != GGML_TYPE_IQ2_XXS && 449op -> type != GGML_TYPE_IQ2_XS && 450op -> type != GGML_TYPE_IQ2_S && 451op -> type != GGML_TYPE_IQ1_S && 452op -> type != GGML_TYPE_IQ1_M ;// missing type_traits.from_float 453case GGML_OP_MUL_MAT : 454return src1 -> type == GGML_TYPE_F32 || src1 -> type == ggml_get_type_traits_cpu (src0 -> type )-> vec_dot_type ; 455case GGML_OP_SOFT_MAX_BACK : { 456if (op -> src [0 ]-> type != GGML_TYPE_F32 || op -> src [1 ]-> type != GGML_TYPE_F32 ) { 457return false; 458 } 459float max_bias = 0.0f ; 460 461memcpy (& max_bias , (const float * )op -> op_params + 1 ,sizeof (float )); 462 463return max_bias == 0.0f ; 464 } 465case GGML_OP_IM2COL_BACK : 466return src0 -> type == GGML_TYPE_F32 && (src1 -> type == GGML_TYPE_F32 || src1 -> type == GGML_TYPE_F16 ); 467case GGML_OP_GET_ROWS_BACK : 468return src0 -> type == GGML_TYPE_F32 || src0 -> type == GGML_TYPE_F16 ; 469case GGML_OP_OUT_PROD : 470return (src0 -> type == GGML_TYPE_F32 || 471 ((src0 -> type == GGML_TYPE_F16 || ggml_is_quantized (src0 -> type ))&& src0 -> ne [2 ]== src1 -> ne [2 ]&& src0 -> ne [3 ]== src1 -> ne [3 ]))&& 472src1 -> type == GGML_TYPE_F32 && op -> type == GGML_TYPE_F32 ; 473case GGML_OP_CONV_2D : 474return ggml_is_contiguous (op -> src [0 ]); 475case GGML_OP_SSM_SCAN : 476return ggml_get_op_params_i32 (op ,0 )== 1 || op -> src [3 ]-> ne [0 ]== 1 ; 477default : 478return true; 479 } 480} 481 482static bool ggml_backend_cpu_device_supports_buft (ggml_backend_dev_t dev ,ggml_backend_buffer_type_t buft ) { 483return ggml_backend_buft_is_host (buft )|| ggml_backend_cpu_is_extra_buffer_type (buft ); 484GGML_UNUSED (dev ); 485} 486 487static const struct ggml_backend_device_i ggml_backend_cpu_device_i = { 488/* .get_name = */ ggml_backend_cpu_device_get_name , 489/* .get_description = */ ggml_backend_cpu_device_get_description , 490/* .get_memory = */ ggml_backend_cpu_device_get_memory , 491/* .get_type = */ ggml_backend_cpu_device_get_type , 492/* .get_props = */ ggml_backend_cpu_device_get_props , 493/* .init_backend = */ ggml_backend_cpu_device_init_backend , 494/* .get_buffer_type = */ ggml_backend_cpu_device_get_buffer_type , 495/* .get_host_buffer_type = */ NULL , 496/* .buffer_from_host_ptr = */ ggml_backend_cpu_device_buffer_from_host_ptr , 497/* .supports_op = */ ggml_backend_cpu_device_supports_op , 498/* .supports_buft = */ ggml_backend_cpu_device_supports_buft , 499/* .offload_op = */ NULL , 500/* .event_new = */ NULL , 501/* .event_free = */ NULL , 502/* .event_synchronize = */ NULL , 503}; 504 505// CPU backend - backend (reg) 506 507static const char * ggml_backend_cpu_reg_get_name (ggml_backend_reg_t reg ) { 508return "CPU" ; 509 510GGML_UNUSED (reg ); 511} 512 513static size_t ggml_backend_cpu_reg_get_device_count (ggml_backend_reg_t reg ) { 514return 1 ; 515 516GGML_UNUSED (reg ); 517} 518 519static ggml_backend_dev_t ggml_backend_cpu_reg_get_device (ggml_backend_reg_t reg ,size_t index ) { 520GGML_ASSERT (index == 0 ); 521 522static ggml_backend_cpu_device_context ctx ; 523static ggml_backend_device ggml_backend_cpu_device = { 524/* .iface = */ ggml_backend_cpu_device_i , 525/* .reg = */ reg , 526/* .context = */ & ctx , 527 }; 528 529return & ggml_backend_cpu_device ; 530} 531 532// This is intended to replace the the ggml_cpu_has_* functions when loading the CPU backend dynamically, 533// and additionally to allow other backends to expose their own list of features that applications can query using the same API 534static ggml_backend_feature * ggml_backend_cpu_get_features (ggml_backend_reg_t reg ) { 535static std::vector < ggml_backend_feature > features = []() { 536ggml_cpu_init (); 537 538 std::vector < ggml_backend_feature > features ; 539if (ggml_cpu_has_sse3 ()) { 540features .push_back ({"SSE3" ,"1" }); 541 } 542if (ggml_cpu_has_ssse3 ()) { 543features .push_back ({"SSSE3" ,"1" }); 544 } 545if (ggml_cpu_has_avx ()) { 546features .push_back ({"AVX" ,"1" }); 547 } 548if (ggml_cpu_has_avx_vnni ()) { 549features .push_back ({"AVX_VNNI" ,"1" }); 550 } 551if (ggml_cpu_has_avx2 ()) { 552features .push_back ({"AVX2" ,"1" }); 553 } 554if (ggml_cpu_has_f16c ()) { 555features .push_back ({"F16C" ,"1" }); 556 } 557if (ggml_cpu_has_fma ()) { 558features .push_back ({"FMA" ,"1" }); 559 } 560if (ggml_cpu_has_bmi2 ()) { 561features .push_back ({"BMI2" ,"1" }); 562 } 563if (ggml_cpu_has_avx512 ()) { 564features .push_back ({"AVX512" ,"1" }); 565 } 566if (ggml_cpu_has_avx512_vbmi ()) { 567features .push_back ({"AVX512_VBMI" ,"1" }); 568 } 569if (ggml_cpu_has_avx512_vnni ()) { 570features .push_back ({"AVX512_VNNI" ,"1" }); 571 } 572if (ggml_cpu_has_avx512_bf16 ()) { 573features .push_back ({"AVX512_BF16" ,"1" }); 574 } 575if (ggml_cpu_has_amx_int8 ()) { 576features .push_back ({"AMX_INT8" ,"1" }); 577 } 578if (ggml_cpu_has_neon ()) { 579features .push_back ({"NEON" ,"1" }); 580 } 581if (ggml_cpu_has_arm_fma ()) { 582features .push_back ({"ARM_FMA" ,"1" }); 583 } 584if (ggml_cpu_has_fp16_va ()) { 585features .push_back ({"FP16_VA" ,"1" }); 586 } 587if (ggml_cpu_has_matmul_int8 ()) { 588features .push_back ({"MATMUL_INT8" ,"1" }); 589 } 590if (ggml_cpu_has_sve ()) { 591features .push_back ({"SVE" ,"1" }); 592 } 593if (ggml_cpu_has_dotprod ()) { 594features .push_back ({"DOTPROD" ,"1" }); 595 } 596if (ggml_cpu_get_sve_cnt ()> 0 ) { 597static std::string sve_cnt = std::to_string (ggml_cpu_get_sve_cnt ()); 598features .push_back ({"SVE_CNT" ,sve_cnt .c_str () }); 599 } 600if (ggml_cpu_has_sme ()) { 601features .push_back ({"SME" ,"1" }); 602 } 603if (ggml_cpu_has_sme2 ()) { 604features .push_back ({"SME2" ,"1" }); 605 } 606if (ggml_cpu_has_riscv_v ()) { 607features .push_back ({"RISCV_V" ,"1" }); 608 } 609if (ggml_cpu_get_rvv_vlen ()> 0 ) { 610static std::string rvv_vlen = std::to_string (ggml_cpu_get_rvv_vlen ()); 611features .push_back ({"RVV_VLEN" ,rvv_vlen .c_str () }); 612 } 613if (ggml_cpu_has_vsx ()) { 614features .push_back ({"VSX" ,"1" }); 615 } 616if (ggml_cpu_has_vxe ()) { 617features .push_back ({"VXE" ,"1" }); 618 } 619if (ggml_cpu_has_wasm_simd ()) { 620features .push_back ({"WASM_SIMD" ,"1" }); 621 } 622if (ggml_cpu_has_llamafile ()) { 623features .push_back ({"LLAMAFILE" ,"1" }); 624 } 625#ifdef GGML_USE_ACCELERATE 626features .push_back ({"ACCELERATE" ,"1" }); 627#endif 628#ifdef GGML_USE_CPU_HBM 629features .push_back ({"CPU_HBM" ,"1" }); 630#endif 631#ifdef GGML_USE_OPENMP 632features .push_back ({"OPENMP" ,"1" }); 633#endif 634#ifdef GGML_USE_CPU_KLEIDIAI 635features .push_back ({"KLEIDIAI" ,"1" }); 636#endif 637#ifdef GGML_USE_CPU_REPACK 638features .push_back ({"REPACK" ,"1" }); 639#endif 640 641features .push_back ({nullptr ,nullptr }); 642 643return features ; 644 }(); 645 646return features .data (); 647 648GGML_UNUSED (reg ); 649} 650 651static void * ggml_backend_cpu_get_proc_address (ggml_backend_reg_t reg ,const char * name ) { 652if (strcmp (name ,"ggml_backend_set_n_threads" )== 0 ) { 653ggml_backend_set_n_threads_t fct = ggml_backend_cpu_set_n_threads ; 654return (void * )fct ; 655 } 656if (strcmp (name ,"ggml_backend_dev_get_extra_bufts" )== 0 ) { 657ggml_backend_dev_get_extra_bufts_t fct = ggml_backend_cpu_device_get_extra_buffers_type ; 658return (void * )fct ; 659 } 660if (strcmp (name ,"ggml_backend_get_features" )== 0 ) { 661return (void * )ggml_backend_cpu_get_features ; 662 } 663if (strcmp (name ,"ggml_backend_set_abort_callback" )== 0 ) { 664return (void * )ggml_backend_cpu_set_abort_callback ; 665 } 666if (strcmp (name ,"ggml_backend_cpu_numa_init" )== 0 ) { 667return (void * )ggml_numa_init ; 668 } 669if (strcmp (name ,"ggml_backend_cpu_is_numa" )== 0 ) { 670return (void * )ggml_is_numa ; 671 } 672if (strcmp (name ,"ggml_backend_cpu_set_use_ref" )== 0 ) { 673return (void * )ggml_backend_cpu_set_use_ref ; 674 } 675 676// threadpool - TODO: move to ggml-base 677if (strcmp (name ,"ggml_threadpool_new" )== 0 ) { 678return (void * )ggml_threadpool_new ; 679 } 680if (strcmp (name ,"ggml_threadpool_free" )== 0 ) { 681return (void * )ggml_threadpool_free ; 682 } 683if (strcmp (name ,"ggml_backend_cpu_set_threadpool" )== 0 ) { 684return (void * )ggml_backend_cpu_set_threadpool ; 685 } 686 687return NULL ; 688 689GGML_UNUSED (reg ); 690} 691 692static const struct ggml_backend_reg_i ggml_backend_cpu_reg_i = { 693/* .get_name = */ ggml_backend_cpu_reg_get_name , 694/* .get_device_count = */ ggml_backend_cpu_reg_get_device_count , 695/* .get_device = */ ggml_backend_cpu_reg_get_device , 696/* .get_proc_address = */ ggml_backend_cpu_get_proc_address , 697}; 698 699ggml_backend_reg_t ggml_backend_cpu_reg (void ) { 700// init CPU feature detection 701ggml_cpu_init (); 702 703static struct ggml_backend_reg ggml_backend_cpu_reg = { 704/* .api_version = */ GGML_BACKEND_API_VERSION , 705/* .iface = */ ggml_backend_cpu_reg_i , 706/* .context = */ NULL , 707 }; 708 709return & ggml_backend_cpu_reg ; 710} 711 712GGML_BACKEND_DL_IMPL (ggml_backend_cpu_reg )