char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
153d324bc
char/aliceai-t5-moe
1#include "ggml-zdnn.h" 2#include "ggml-impl.h" 3#include "ggml-backend-impl.h" 4 5#include "ggml-zdnn/common.hpp" 6#include "ggml-zdnn/mmf.hpp" 7#include "ggml-zdnn/utils.hpp" 8#include "ggml.h" 9 10#include <vector> 11#include <memory> 12#include <csignal> // raise(SIGTRAP) 13#include <unistd.h> 14 15static void ggml_zdnn_compute_forward_mul_mat ( 16const ggml_backend_zdnn_context * ctx , 17ggml_tensor * dst ) { 18 19const ggml_tensor * src0 = dst -> src [0 ];// weights 20const ggml_tensor * src1 = dst -> src [1 ];// inputs 21 22// TODO: implement support for quantized types 23// we currently only support f32, f16, and bf16 24ggml_zdnn_mul_mat_f (ctx ,src0 ,src1 ,dst ); 25} 26 27static bool ggml_zdnn_compute_forward ( 28ggml_backend_zdnn_context * ctx , 29ggml_tensor * dst ) { 30 31switch (dst -> op ) { 32case GGML_OP_MUL_MAT : 33 { 34ggml_zdnn_compute_forward_mul_mat (ctx ,dst ); 35 }break ; 36 37default : 38return false; 39 } 40 41return true; 42} 43 44static enum ggml_status ggml_zdnn_graph_compute (ggml_backend_t backend ,ggml_cgraph * gf ) { 45ggml_backend_zdnn_context * ctx = (ggml_backend_zdnn_context * )backend -> context ; 46ggml_backend_zdnn_device_context * ctx_dev = (ggml_backend_zdnn_device_context * )backend -> device -> context ; 47 48ctx -> gf = gf ; 49for (int i = 0 ;i < gf -> n_nodes ;i ++ ) { 50ggml_tensor * node = gf -> nodes [i ]; 51 52if (ggml_is_empty (node ) 53|| node -> op == GGML_OP_NONE 54|| node -> op == GGML_OP_RESHAPE 55|| node -> op == GGML_OP_VIEW 56|| node -> op == GGML_OP_PERMUTE 57|| node -> op == GGML_OP_TRANSPOSE ) { 58continue ; 59 } 60 61if ((node -> flags & GGML_TENSOR_FLAG_COMPUTE )== 0 ) { 62continue ; 63 } 64 65bool ok = ggml_zdnn_compute_forward (ctx ,node ); 66if (!ok ) { 67GGML_LOG_ERROR ("%s: unsupported op %s (%s)\n" , 68__func__ ,node -> name ,ggml_op_name (node -> op )); 69 } 70 71GGML_ASSERT (ok ); 72 } 73 74return GGML_STATUS_SUCCESS ; 75 76GGML_UNUSED (ctx_dev ); 77} 78 79static bool ggml_zdnn_supports_op (const ggml_backend_zdnn_device_context * ctx_dev ,const ggml_tensor * op ) { 80switch (op -> op ) { 81case GGML_OP_NONE : 82case GGML_OP_RESHAPE : 83case GGML_OP_VIEW : 84case GGML_OP_TRANSPOSE : 85case GGML_OP_PERMUTE : 86return true; 87 88case GGML_OP_MUL_MAT : 89 { 90const ggml_tensor * weights = op -> src [0 ]; 91const ggml_tensor * inputs = op -> src [1 ]; 92 93const int64_t ne10 = inputs -> ne [0 ]; 94const int64_t ne0 = op -> ne [0 ]; 95const int64_t ne1 = op -> ne [1 ]; 96 97const int64_t max_batch = ctx_dev -> max_size ; 98 99if (!ggml_is_matrix (weights )|| !ggml_is_matrix (inputs )|| 100 !ggml_is_contiguous (weights )|| !ggml_is_contiguous (inputs )|| 101weights -> view_src != nullptr || inputs -> view_src != nullptr || 102ne0 > max_batch || ne1 > max_batch || ne10 > max_batch ) { 103return false; 104 } 105 106switch (weights -> type ) { 107case GGML_TYPE_F32 : 108case GGML_TYPE_F16 : 109case GGML_TYPE_BF16 : 110return true; 111default : 112return false; 113 } 114 }break ; 115 116default : 117return false; 118 } 119} 120 121//////////////////////////////////////////////////////////////////////////////// 122 123// 124// globals 125// 126 127// initialised in ggml_backend_zdnn_reg 128static ggml_backend_reg g_ggml_backend_zdnn_reg ; 129static ggml_backend_device g_ggml_backend_zdnn_device ; 130 131static ggml_backend_zdnn_device_context g_ggml_ctx_dev_main = { 132/* .zdnn_device = */ 0 , 133/* .zdnn_device_ref_count = */ 0 , 134/* .has_parmblkformat_0 = */ false, 135/* .has_parmblkformat_1 = */ false, 136/* .max_size = */ 0 , 137/* .name = */ "" , 138}; 139 140static int ggml_backend_zdnn_device_acq (ggml_backend_zdnn_device_context * ctx ) { 141assert (ctx != NULL ); 142 143if (ctx -> zdnn_device == 0 ) { 144ctx -> zdnn_device = 1 ; 145 } 146 147if (ctx -> zdnn_device >=1 ) { 148ctx -> has_parmblkformat_0 = zdnn_is_nnpa_parmblk_fmt_installed (1 ,NNPA_PARMBLKFORMAT_0 ); 149ctx -> has_parmblkformat_1 = zdnn_is_nnpa_parmblk_fmt_installed (1 ,NNPA_PARMBLKFORMAT_1 ); 150ctx -> max_size = zdnn_get_nnpa_max_dim_idx_size (); 151strncpy (ctx -> name ,GGML_ZDNN_NAME ,sizeof (ctx -> name )- 1 ); 152 } 153 154ctx -> zdnn_device_ref_count ++ ; 155return ctx -> zdnn_device ; 156} 157 158static void ggml_backend_zdnn_device_rel (ggml_backend_zdnn_device_context * ctx ) { 159assert (ctx != NULL ); 160assert (ctx -> zdnn_device_ref_count > 0 ); 161 162ctx -> zdnn_device_ref_count -- ; 163if (ctx -> zdnn_device_ref_count == 0 ) { 164if (ctx -> zdnn_device >=0 ) { 165ctx -> zdnn_device = 0 ; 166 } 167 } 168} 169 170static ggml_backend_zdnn_context * ggml_zdnn_init (ggml_backend_dev_t dev ) { 171GGML_LOG_INFO ("%s: allocating\n" ,__func__ ); 172GGML_LOG_INFO ("%s: found 1 device\n" ,__func__ ); 173 174#ifdef STATIC_LIB 175zdnn_init (); 176#endif 177 178ggml_backend_zdnn_context * ctx = new ggml_backend_zdnn_context (); 179ggml_backend_zdnn_device_context * ctx_dev = (ggml_backend_zdnn_device_context * )dev -> context ; 180 181int device = 1 ; 182GGML_LOG_INFO ("%s: picking default device: %s\n" ,__func__ ,ctx_dev -> name ); 183 184ctx -> device = device ; 185GGML_LOG_INFO ("%s: NNPA name: %s\n" ,__func__ ,ctx_dev -> name ); 186GGML_LOG_INFO ("%s: NNPA_PARMBLKFORMAT_0 = %s\n" ,__func__ ,ctx_dev -> has_parmblkformat_0 ?"true" :"false" ); 187GGML_LOG_INFO ("%s: NNPA_PARMBLKFORMAT_1 = %s\n" ,__func__ ,ctx_dev -> has_parmblkformat_1 ?"true" :"false" ); 188 189ctx -> gf = nullptr ; 190 191return ctx ; 192} 193 194static void ggml_zdnn_free (ggml_backend_zdnn_context * ctx ) { 195GGML_LOG_INFO ("%s: deallocating\n" ,__func__ ); 196delete ctx ; 197} 198 199// 200// backend interface 201// 202 203static void ggml_backend_zdnn_buffer_free_buffer (ggml_backend_buffer_t buffer ) { 204ggml_backend_zdnn_buffer_context * ctx = (ggml_backend_zdnn_buffer_context * )buffer -> context ; 205 206for (const auto & buf_ptr :ctx -> buffers ) { 207ggml_backend_zdnn_buffer * buf = buf_ptr .get (); 208 209// Free any extra buffer allocated for the tensor. E.g., bias for GGML_OP_MUL_MAT 210if (buf -> extra != nullptr )free (buf -> extra -> data ); 211if (buf -> ztensor .buffer_size > 0 )ZDNN_CHECK (zdnn_free_ztensor_buffer (& buf -> ztensor )); 212 } 213 214delete ctx ; 215} 216 217static void * ggml_backend_zdnn_buffer_get_base (ggml_backend_buffer_t buffer ) { 218ggml_backend_zdnn_buffer_context * ctx = (ggml_backend_zdnn_buffer_context * )buffer -> context ; 219return ctx -> all_data ; 220} 221 222static enum ggml_status ggml_backend_zdnn_buffer_init_tensor (ggml_backend_buffer_t buffer ,ggml_tensor * tensor ) { 223if (tensor -> view_src != NULL ) { 224assert (tensor -> view_src -> buffer -> buft == buffer -> buft ); 225return GGML_STATUS_SUCCESS ; 226 } 227 228ggml_backend_zdnn_buffer_context * ctx = (ggml_backend_zdnn_buffer_context * )buffer -> context ; 229 230const int64_t tsize = ggml_nbytes (tensor ); 231int buffer_idx = ctx -> n_buffers ; 232 233 std::unique_ptr < ggml_backend_zdnn_buffer > zdnn_buffer = std::make_unique < ggml_backend_zdnn_buffer > (); 234zdnn_buffer -> data = tensor -> data ; 235zdnn_buffer -> size = tsize ; 236zdnn_buffer -> extra = nullptr ; 237snprintf (zdnn_buffer -> name ,GGML_MAX_NAME ,"%s" ,tensor -> name ); 238 239ggml_zdnn_init_tensor (zdnn_buffer .get (),tensor ); 240tensor -> extra = zdnn_buffer .get (); 241 242switch (tensor -> op ) { 243case GGML_OP_MUL_MAT : 244 { 245 std::unique_ptr < ggml_backend_zdnn_buffer > zdnn_bias_buffer = std::make_unique < ggml_backend_zdnn_buffer > (); 246zdnn_bias_buffer -> data = (void * )calloc (tensor -> ne [0 ],ggml_element_size (tensor )); 247zdnn_bias_buffer -> size = ggml_element_size (tensor )* tensor -> ne [0 ]; 248snprintf (zdnn_bias_buffer -> name ,GGML_MAX_NAME ,"%.*s (bias)" , 249GGML_MAX_NAME - (int )sizeof (" (bias)" ),tensor -> name ); 250 251const int64_t bias_dim [GGML_MAX_DIMS ]= {1 ,1 ,1 ,tensor -> ne [0 ] }; 252ggml_zdnn_create_tensor (zdnn_bias_buffer -> pre_tfm_desc , 253zdnn_bias_buffer -> tfm_desc , 254zdnn_bias_buffer -> ztensor , 255tensor ,bias_dim ,ZDNN_1D ); 256 257ggml_zdnn_load_tensor (zdnn_bias_buffer -> ztensor ,zdnn_bias_buffer -> data ); 258zdnn_buffer -> extra = zdnn_bias_buffer .get (); 259 260ctx -> buffers .push_back (std::move (zdnn_bias_buffer )); 261ctx -> n_buffers ++ ; 262 }break ; 263default : 264break ; 265 } 266 267ctx -> buffers .push_back (std::move (zdnn_buffer )); 268ctx -> n_buffers ++ ; 269 270// GGML_LOG_INFO("%s: initialised tensor '%s' in buffer %d, size = %8.2f MiB\n", 271// __func__, tensor->name, buffer_idx, tsize); 272 273return GGML_STATUS_SUCCESS ; 274 275GGML_UNUSED (buffer_idx ); 276} 277 278static void ggml_backend_zdnn_buffer_memset_tensor (ggml_backend_buffer_t buffer ,ggml_tensor * tensor ,uint8_t value ,size_t offset ,size_t size ) { 279memset ((char * )tensor -> data + offset ,value ,size ); 280 281GGML_UNUSED (buffer ); 282} 283 284static void ggml_backend_zdnn_buffer_set_tensor (ggml_backend_buffer_t buffer ,ggml_tensor * tensor ,const void * data ,size_t offset ,size_t size ) { 285memcpy ((char * )tensor -> data + offset ,data ,size ); 286 287ggml_backend_zdnn_buffer * extra = (ggml_backend_zdnn_buffer * )tensor -> extra ; 288 289// Fixes the LLAMA_SET_ROWS bug 290// see: https://github.com/ggml-org/llama.cpp/issues/15414 291if (tensor -> buffer -> usage == GGML_BACKEND_BUFFER_USAGE_COMPUTE && extra -> ztensor .is_transformed )zdnn_reset_ztensor (& extra -> ztensor ); 292if (extra -> ztensor .is_transformed == false)ggml_zdnn_load_tensor (extra -> ztensor ,tensor -> data ); 293 294GGML_UNUSED (buffer ); 295} 296 297static void ggml_backend_zdnn_buffer_get_tensor (ggml_backend_buffer_t buffer ,const ggml_tensor * tensor ,void * data ,size_t offset ,size_t size ) { 298memcpy (data , (const char * )tensor -> data + offset ,size ); 299 300GGML_UNUSED (buffer ); 301} 302 303static void ggml_backend_zdnn_buffer_clear (ggml_backend_buffer_t buffer ,uint8_t value ) { 304ggml_backend_zdnn_buffer_context * ctx = (ggml_backend_zdnn_buffer_context * )buffer -> context ; 305 306memset (ctx -> all_data ,value ,ctx -> all_size ); 307} 308 309static ggml_backend_buffer_i ggml_backend_zdnn_buffer_i = { 310/* .free_buffer = */ ggml_backend_zdnn_buffer_free_buffer , 311/* .get_base = */ ggml_backend_zdnn_buffer_get_base , 312/* .init_tensor = */ ggml_backend_zdnn_buffer_init_tensor , 313/* .memset_tensor = */ ggml_backend_zdnn_buffer_memset_tensor , 314/* .set_tensor = */ ggml_backend_zdnn_buffer_set_tensor , 315/* .get_tensor = */ ggml_backend_zdnn_buffer_get_tensor , 316/* .set_tensor_2d = */ NULL , 317/* .get_tensor_2d = */ NULL , 318/* .cpy_tensor = */ NULL , 319/* .clear = */ ggml_backend_zdnn_buffer_clear , 320/* .reset = */ NULL , 321}; 322 323// 324// default buffer type 325// 326 327static const char * ggml_backend_zdnn_buffer_type_get_name (ggml_backend_buffer_type_t buft ) { 328return GGML_ZDNN_NAME ; 329 330GGML_UNUSED (buft ); 331} 332 333static ggml_backend_buffer_t ggml_backend_zdnn_buffer_type_alloc_buffer (ggml_backend_buffer_type_t buft ,size_t size ) { 334ggml_backend_zdnn_buffer_context * ctx = new ggml_backend_zdnn_buffer_context (); 335 336const size_t size_page = sysconf (_SC_PAGESIZE ); 337 338size_t size_aligned = size ; 339if ((size_aligned %size_page )!= 0 ) { 340size_aligned += size_page - (size_aligned %size_page ); 341 } 342 343ggml_backend_zdnn_device_context * ctx_dev = (ggml_backend_zdnn_device_context * )buft -> device -> context ; 344 345GGML_ASSERT (ctx_dev -> zdnn_device >=0 ); 346int device = ctx_dev -> zdnn_device ;GGML_UNUSED (device ); 347 348ctx -> all_data = ggml_aligned_malloc (size_aligned ); 349ctx -> all_size = size_aligned ; 350ctx -> owned = true; 351ctx -> n_buffers = 1 ; 352 353if (ctx -> all_data != NULL ) { 354 std::unique_ptr < ggml_backend_zdnn_buffer > zdnn_buffer = std::make_unique < ggml_backend_zdnn_buffer > (); 355zdnn_buffer -> data = ctx -> all_data ; 356zdnn_buffer -> size = size_aligned ; 357ctx -> buffers .push_back (std::move (zdnn_buffer )); 358 } 359 360if (size_aligned > 0 && (ctx -> all_data == NULL )) { 361GGML_LOG_ERROR ("%s: error: failed to allocate buffer, size = %8.2f\n" , 362__func__ ,size_aligned /1024.0 /1024.0 ); 363delete ctx ; 364return NULL ; 365 } 366 367return ggml_backend_buffer_init (buft ,ggml_backend_zdnn_buffer_i ,ctx ,size ); 368} 369 370static size_t ggml_backend_zdnn_buffer_type_get_alignment (ggml_backend_buffer_type_t buft ) { 371return 256 ; 372 373GGML_UNUSED (buft ); 374} 375 376static bool ggml_backend_zdnn_buffer_type_is_host (ggml_backend_buffer_type_t buft ) { 377/* while it resides in host memory, additional transformation is needed */ 378return false; 379 380GGML_UNUSED (buft ); 381} 382 383ggml_backend_buffer_type_t ggml_backend_zdnn_buffer_type (void ) { 384static ggml_backend_buffer_type ggml_backend_buffer_type_zdnn = { 385/* .iface = */ { 386/* .get_name = */ ggml_backend_zdnn_buffer_type_get_name , 387/* .alloc_buffer = */ ggml_backend_zdnn_buffer_type_alloc_buffer , 388/* .get_alignment = */ ggml_backend_zdnn_buffer_type_get_alignment , 389/* .get_max_size = */ NULL , 390/* .get_alloc_size = */ NULL ,// defaults to ggml_nbytes 391/* .is_host = */ ggml_backend_zdnn_buffer_type_is_host , 392 }, 393/* .device = */ & g_ggml_backend_zdnn_device , 394/* .context = */ NULL , 395 }; 396 397return & ggml_backend_buffer_type_zdnn ; 398} 399 400// 401// backend 402// 403 404static const char * ggml_backend_zdnn_name (ggml_backend_t backend ) { 405return GGML_ZDNN_NAME ; 406 407GGML_UNUSED (backend ); 408} 409 410static void ggml_backend_zdnn_free (ggml_backend_t backend ) { 411ggml_backend_zdnn_context * ctx = (ggml_backend_zdnn_context * )backend -> context ; 412 413ggml_zdnn_free (ctx ); 414free (backend ); 415} 416 417static enum ggml_status ggml_backend_zdnn_graph_compute (ggml_backend_t backend ,ggml_cgraph * cgraph ) { 418return ggml_zdnn_graph_compute (backend ,cgraph ); 419} 420 421static ggml_backend_i ggml_backend_zdnn_i = { 422/* .get_name = */ ggml_backend_zdnn_name , 423/* .free = */ ggml_backend_zdnn_free , 424/* .set_tensor_async = */ NULL , 425/* .get_tensor_async = */ NULL , 426/* .set_tensor_2d_async = */ NULL , 427/* .get_tensor_2d_async = */ NULL , 428/* .cpy_tensor_async = */ NULL , 429/* .synchronize = */ NULL , 430/* .graph_plan_create = */ NULL , 431/* .graph_plan_free = */ NULL , 432/* .graph_plan_update = */ NULL , 433/* .graph_plan_compute = */ NULL , 434/* .graph_compute = */ ggml_backend_zdnn_graph_compute , 435/* .event_record = */ NULL , 436/* .event_wait = */ NULL , 437/* .graph_optimize = */ NULL , 438}; 439 440static ggml_guid_t ggml_backend_zdnn_guid (void ) { 441static const char * guid_str = "IBM-ZDNN-ACCELER" ; 442return reinterpret_cast < ggml_guid_t > ((void * )guid_str ); 443} 444 445bool ggml_backend_is_zdnn (ggml_backend_t backend ) { 446return backend != NULL && 447ggml_guid_matches (backend -> guid ,ggml_backend_zdnn_guid ()); 448 449GGML_UNUSED (backend ); 450} 451 452// 453// backend device 454// 455 456static const char * ggml_backend_zdnn_device_get_name (ggml_backend_dev_t dev ) { 457return GGML_ZDNN_NAME ; 458 459GGML_UNUSED (dev ); 460} 461 462static const char * ggml_backend_zdnn_device_get_description (ggml_backend_dev_t dev ) { 463return "IBM Z Neural Network Processing Assist (NNPA)" ; 464 465GGML_UNUSED (dev ); 466} 467 468static void ggml_backend_zdnn_device_get_memory (ggml_backend_dev_t dev ,size_t * free ,size_t * total ) { 469* free = 0 ; 470* total = 0 ; 471 472GGML_UNUSED (dev ); 473} 474 475static enum ggml_backend_dev_type ggml_backend_zdnn_device_get_type (ggml_backend_dev_t dev ) { 476return GGML_BACKEND_DEVICE_TYPE_ACCEL ; 477 478GGML_UNUSED (dev ); 479} 480 481static void ggml_backend_zdnn_device_get_props (ggml_backend_dev_t dev ,ggml_backend_dev_props * props ) { 482props -> name = ggml_backend_zdnn_device_get_name (dev ); 483props -> description = ggml_backend_zdnn_device_get_description (dev ); 484props -> type = ggml_backend_zdnn_device_get_type (dev ); 485ggml_backend_zdnn_device_get_memory (dev ,& props -> memory_free ,& props -> memory_total ); 486props -> caps = (ggml_backend_dev_caps ) { 487/* .async = */ false, 488/* .host_buffer = */ false, 489/* .buffer_from_host_ptr = */ false, 490/* .events = */ false, 491/* .mmap_support = */ true, 492 }; 493} 494 495static ggml_backend_t ggml_backend_zdnn_device_init (ggml_backend_dev_t dev ,const char * params ) { 496ggml_backend_zdnn_context * ctx = ggml_zdnn_init (dev ); 497if (ctx == NULL ) { 498GGML_LOG_ERROR ("%s: error: failed to allocate context\n" ,__func__ ); 499return NULL ; 500 } 501 502ggml_backend_t backend = (ggml_backend * )malloc (sizeof (ggml_backend )); 503* backend = (ggml_backend ) { 504/* .guid = */ ggml_backend_zdnn_guid (), 505/* .iface = */ ggml_backend_zdnn_i , 506/* .device = */ dev , 507/* .context = */ ctx 508 }; 509 510return backend ; 511 512GGML_UNUSED (params ); 513} 514 515static ggml_backend_buffer_type_t ggml_backend_zdnn_device_get_buffer_type (ggml_backend_dev_t dev ) { 516return ggml_backend_zdnn_buffer_type (); 517 518GGML_UNUSED (dev ); 519} 520 521static bool ggml_backend_zdnn_device_supports_op (ggml_backend_dev_t dev ,const ggml_tensor * op ) { 522ggml_backend_zdnn_device_context * ctx_dev = (ggml_backend_zdnn_device_context * )dev -> context ; 523 524return ggml_zdnn_supports_op (ctx_dev ,op ); 525} 526 527static bool ggml_backend_zdnn_device_supports_buft (ggml_backend_dev_t dev ,ggml_backend_buffer_type_t buft ) { 528return 529buft -> iface .get_name == ggml_backend_zdnn_buffer_type_get_name ; 530 531GGML_UNUSED (dev ); 532} 533 534static ggml_backend_device_i ggml_backend_zdnn_device_i = { 535/* .get_name = */ ggml_backend_zdnn_device_get_name , 536/* .get_description = */ ggml_backend_zdnn_device_get_description , 537/* .get_memory = */ ggml_backend_zdnn_device_get_memory , 538/* .get_type = */ ggml_backend_zdnn_device_get_type , 539/* .get_props = */ ggml_backend_zdnn_device_get_props , 540/* .init_backend = */ ggml_backend_zdnn_device_init , 541/* .get_buffer_type = */ ggml_backend_zdnn_device_get_buffer_type , 542/* .get_host_buffer_type = */ NULL , 543/* .buffer_from_host_ptr = */ NULL , 544/* .supports_op = */ ggml_backend_zdnn_device_supports_op , 545/* .supports_buft = */ ggml_backend_zdnn_device_supports_buft , 546/* .offload_op = */ NULL , 547/* .event_new = */ NULL , 548/* .event_free = */ NULL , 549/* .event_synchronize = */ NULL , 550}; 551 552// 553// backend registry 554// 555 556static const char * ggml_backend_zdnn_reg_get_name (ggml_backend_reg_t reg ) { 557return GGML_ZDNN_NAME ; 558 559GGML_UNUSED (reg ); 560} 561 562static size_t ggml_backend_zdnn_reg_device_count (ggml_backend_reg_t reg ) { 563if (!zdnn_is_nnpa_installed ()) { 564return 0 ; 565 } 566return 1 ; 567 568GGML_UNUSED (reg ); 569} 570 571static ggml_backend_dev_t ggml_backend_zdnn_reg_device_get (ggml_backend_reg_t reg ,size_t index ) { 572GGML_ASSERT (index == 0 ); 573 574return & g_ggml_backend_zdnn_device ; 575 576GGML_UNUSED (reg ); 577GGML_UNUSED (index ); 578} 579 580static ggml_backend_feature g_ggml_backend_zdnn_features []= { 581 {"NNPA" ,zdnn_is_nnpa_installed () ?"1" :"0" }, 582 {"NNPA_PARMBLKFORMAT_0" ,zdnn_is_nnpa_parmblk_fmt_installed (1 ,NNPA_PARMBLKFORMAT_0 ) ?"1" :"0" }, 583 {"NNPA_PARMBLKFORMAT_1" ,zdnn_is_nnpa_parmblk_fmt_installed (1 ,NNPA_PARMBLKFORMAT_1 ) ?"1" :"0" }, 584 {NULL ,NULL }, 585}; 586 587static ggml_backend_feature * ggml_backend_zdnn_get_features (ggml_backend_reg_t reg ) { 588return g_ggml_backend_zdnn_features ; 589 590GGML_UNUSED (reg ); 591} 592 593static void * ggml_backend_zdnn_get_proc_address (ggml_backend_reg_t reg ,const char * name ) { 594if (strcmp (name ,"ggml_backend_get_features" )== 0 ) { 595return (void * )ggml_backend_zdnn_get_features ; 596 } 597 598return NULL ; 599 600GGML_UNUSED (reg ); 601} 602 603static ggml_backend_reg_i ggml_backend_zdnn_reg_i = { 604/* .get_name = */ ggml_backend_zdnn_reg_get_name , 605/* .get_device_count = */ ggml_backend_zdnn_reg_device_count , 606/* .get_device = */ ggml_backend_zdnn_reg_device_get , 607/* .get_proc_address = */ ggml_backend_zdnn_get_proc_address 608}; 609 610static void ggml_zdnn_cleanup (void ) { 611ggml_backend_zdnn_device_rel (& g_ggml_ctx_dev_main ); 612} 613 614// TODO: make thread-safe 615ggml_backend_reg_t ggml_backend_zdnn_reg (void ) { 616ggml_backend_zdnn_device_acq (& g_ggml_ctx_dev_main ); 617 618// register cleanup callback 619atexit (ggml_zdnn_cleanup ); 620 621 { 622g_ggml_backend_zdnn_reg = (ggml_backend_reg ) { 623/* .api_version = */ GGML_ZDNN_VERSION , 624/* .iface = */ ggml_backend_zdnn_reg_i , 625/* .context = */ NULL 626 }; 627 628g_ggml_backend_zdnn_device = (ggml_backend_device ) { 629/* .iface = */ ggml_backend_zdnn_device_i , 630/* .reg = */ & g_ggml_backend_zdnn_reg , 631/* .context = */ & g_ggml_ctx_dev_main 632 }; 633 634return & g_ggml_backend_zdnn_reg ; 635 } 636} 637 638GGML_BACKEND_DL_IMPL (ggml_backend_zdnn_reg )