char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
632219af7
char/aliceai-t5-moe
1/* 2* Copyright (c) 2023-2026 The ggml authors 3* 4* Permission is hereby granted, free of charge, to any person obtaining a copy 5* of this software and associated documentation files (the "Software"), to 6* deal in the Software without restriction, including without limitation the 7* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8* sell copies of the Software, and to permit persons to whom the Software is 9* furnished to do so, subject to the following conditions: 10* 11* The above copyright notice and this permission notice shall be included in 12* all copies or substantial portions of the Software. 13* 14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20* IN THE SOFTWARE. 21*/ 22 23#ifndef CANN_COMMON_H 24#define CANN_COMMON_H 25 26#include "../ggml-impl.h" 27#include "../include/ggml-cann.h" 28#include "../include/ggml.h" 29 30#include <acl/acl.h> 31#include <unistd.h> 32 33#include <atomic> 34#include <condition_variable> 35#include <cstdio> 36#include <functional> 37#include <iostream> 38#include <list> 39#include <map> 40#include <memory> 41#include <mutex> 42#include <optional> 43#include <string> 44#include <thread> 45#include <vector> 46 47#define MATRIX_ROW_PADDING 512 48#define GGML_CANN_MAX_STREAMS 8 49 50/** 51* @brief Handles CANN-related errors by printing an error message and 52* terminating the program. 53* @param stmt The statement that caused the error. 54* @param func The function in which the error occurred. 55* @param file The file in which the error occurred. 56* @param line The line number at which the error occurred. 57* @param msg The error message. 58*/ 59[[noreturn ]]void ggml_cann_error (const char * stmt ,const char * func ,const char * file ,int line ,const char * msg ); 60 61/** 62* @brief Checks the result of a CANN function call and invokes the error 63* handler if the call fails. 64* @param stmt The CANN function call to check. 65* @param success The success code that indicates the call was successful. 66* @param error_fn The function to call to retrieve the error message. 67*/ 68#define ACL_CHECK_GEN (stmt ,success ,error_fn ) \ 69 do { \ 70 int err_code = (stmt); \ 71 if (err_code != (success)) { \ 72 ggml_cann_error(#stmt, __func__, __FILE__, __LINE__, error_fn()); \ 73 } \ 74 } while (0); 75 76#define ACL_CHECK (stmt ) ACL_CHECK_GEN(stmt, 0, aclGetRecentErrMsg) 77 78/** 79* @brief Contains information about CANN devices. 80*/ 81struct ggml_cann_device_info { 82/** 83* @brief Number of CANN devices available. 84*/ 85int32_t device_count ; 86 87/** 88* @brief Information about a single CANN device. 89*/ 90struct cann_device_info { 91int cc ;/**< Compute capability. */ 92size_t smpb ;/**< Maximum shared memory per block. */ 93bool vmm ;/**< Virtual memory support. */ 94size_t vmm_granularity ;/**< Granularity of virtual memory. */ 95size_t total_vram ;/**< Total video RAM available on the device. */ 96 }; 97 98cann_device_info devices [GGML_CANN_MAX_DEVICES ]= {};/**< Array of CANN device information. */ 99}; 100 101const ggml_cann_device_info & ggml_cann_info (); 102 103void ggml_cann_set_device (int32_t device ); 104 105std ::optional < std ::string > get_env_as_lowercase (const std ::string & name ); 106bool parse_bool (const std ::string & value ); 107int parse_integer (const std ::string & value ); 108 109/** 110* @brief Abstract base class for memory pools used by CANN. 111*/ 112struct ggml_cann_pool { 113/** 114* @brief Virtual destructor for the memory pool. 115*/ 116virtual ~ggml_cann_pool ()= default ; 117 118/** 119* @brief Allocates memory from the pool. 120* 121* @param size The size of the memory block to allocate. 122* @param actual_size Pointer to a variable where the actual allocated size 123* will be stored. 124* @return Pointer to the allocated memory block. 125*/ 126virtual void * alloc (size_t size ,size_t * actual_size )= 0 ; 127 128/** 129* @brief Frees a previously allocated memory block. 130* 131* @param ptr Pointer to the memory block to free. 132* @param size Size of the memory block to free. 133* @note Note that all CANN opertors are running async. Make sure memory is 134* still avaiable before this operator finished. 135*/ 136virtual void free (void * ptr ,size_t size )= 0 ; 137}; 138 139/** 140* @brief RAII wrapper for managing memory allocations from a CANN memory pool. 141*/ 142struct ggml_cann_pool_alloc { 143ggml_cann_pool * pool = nullptr;/**< Pointer to the memory pool. */ 144void * ptr = nullptr;/**< Pointer to the allocated memory block. */ 145size_t actual_size = 0 ;/**< Actual size of the allocated memory block. */ 146 147/** 148* @brief Default constructor. 149*/ 150ggml_cann_pool_alloc ()= default ; 151 152/** 153* @brief Constructor that initializes the memory pool. 154* @param pool Reference to the memory pool. 155*/ 156explicit ggml_cann_pool_alloc (ggml_cann_pool & pool ) :pool (& pool ) {} 157 158/** 159* @brief Constructor that initializes the memory pool and allocates memory. 160* @param pool Reference to the memory pool. 161* @param size Size of the memory block to allocate. 162*/ 163ggml_cann_pool_alloc (ggml_cann_pool & pool ,size_t size ) :pool (& pool ) {alloc (size ); } 164 165/** 166* @brief Destructor that frees the allocated memory block. 167*/ 168 ~ggml_cann_pool_alloc () { 169if (ptr != nullptr ) { 170pool -> free (ptr ,actual_size ); 171 } 172 } 173 174/** 175* @brief Allocates memory from the pool. 176* @param size Size of the memory block to allocate. 177* @return Pointer to the allocated memory block. 178*/ 179void * alloc (size_t size ) { 180GGML_ASSERT (pool != nullptr ); 181GGML_ASSERT (ptr == nullptr ); 182ptr = pool -> alloc (size ,& this -> actual_size ); 183return ptr ; 184 } 185 186/** 187* @brief Allocates memory from a specific memory pool. 188* @param pool Reference to the memory pool. 189* @param size Size of the memory block to allocate. 190* @return Pointer to the allocated memory block. 191*/ 192void * alloc (ggml_cann_pool & pool ,size_t size ) { 193this -> pool = & pool ; 194return alloc (size ); 195 } 196 197/** 198* @brief Gets the pointer to the allocated memory block. 199* @return Pointer to the allocated memory block. 200*/ 201void * get () {return ptr ; } 202 203// Deleted copy constructor 204ggml_cann_pool_alloc (const ggml_cann_pool_alloc & )= delete ; 205 206// Deleted move constructor 207ggml_cann_pool_alloc (ggml_cann_pool_alloc && ) = delete; 208 209// Deleted copy assignment operator 210ggml_cann_pool_alloc & operator = ( const ggml_cann_pool_alloc & ) = delete; 211 212// Deleted move assignment operator 213ggml_cann_pool_alloc & operator = (ggml_cann_pool_alloc && ) = delete; 214}; 215 216#ifdef USE_ACL_GRAPH 217struct ggml_graph_node_properties { 218// dst tensor 219void * node_address ; 220ggml_type node_type ; 221int64_t ne [ GGML_MAX_DIMS ]; 222size_t nb [ GGML_MAX_DIMS ]; 223 224// src tensor 225void * src_address [ GGML_MAX_SRC ]; 226ggml_type src_type [ GGML_MAX_SRC ]; 227int64_t src_ne [ GGML_MAX_SRC ][ GGML_MAX_DIMS ]; 228size_t src_nb [ GGML_MAX_SRC ][ GGML_MAX_DIMS ]; 229 230// op 231ggml_op node_op ; 232int32_t op_params [ GGML_MAX_OP_PARAMS / sizeof ( int32_t )]; 233 234/** 235* @brief Check if a ggml tensor node matches this property set. 236* 237* This function compares all relevant fields (address, op type, shape, source inputs, op params) 238* to determine whether the current node matches these previously recorded properties. 239* 240* @param node The current ggml tensor node. 241* @return true if all fields match (excluding GGML_OP_VIEW); false otherwise. 242*/ 243bool has_matching_properties ( ggml_tensor * node) { 244if ( node -> data != this -> node_address && node -> op != GGML_OP_VIEW ) { 245return false; 246} 247 248if ( node -> op != this -> node_op) { 249return false; 250} 251 252if (node -> type != this -> node_type ) { 253return false; 254} 255 256for ( int i = 0 ; i < GGML_MAX_DIMS ; i ++ ) { 257if (node -> ne [i] != this -> ne [i]) { 258return false; 259} 260if (node -> nb [i] != this -> nb [i]) { 261return false; 262} 263} 264 265for ( int i = 0 ; i < GGML_MAX_SRC ; i ++ ) { 266if (node -> src [i]) { 267if (node -> src [i] -> data != this -> src_address [i] && node -> op != GGML_OP_VIEW ) { 268return false; 269} 270 271if (node -> src [i] -> type != this -> src_type [i]) { 272return false; 273} 274 275for ( int d = 0 ; d < GGML_MAX_DIMS ; d ++ ) { 276if (node -> src [i] -> ne [d] != this -> src_ne [i][d]) { 277return false; 278} 279if (node -> src [i] -> nb [d] != this -> src_nb [i][d]) { 280return false; 281} 282} 283} else { 284if (this -> src_address [i] != nullptr ) { 285return false; 286} 287} 288} 289 290return memcmp (this -> op_params , node -> op_params , GGML_MAX_OP_PARAMS ) == 0 ; 291} 292}; 293 294struct ggml_cann_graph { 295~ ggml_cann_graph () { 296if (graph != nullptr ) { 297ACL_CHECK ( aclmdlRIDestroy (graph)); 298} 299} 300 301aclmdlRI graph = nullptr ; 302 303std ::vector < ggml_graph_node_properties > ggml_graph_properties; 304 305/** 306* @brief Create a new CANN graph from a ggml computation graph. 307* 308* This function creates a new ggml_cann_graph object and fills its node properties 309* (operation type, dimensions, strides, input sources, and operation parameters) 310* based on the current ggml computation graph. 311* 312* Each node in the ggml graph is mapped to a property entry in the new CANN graph: 313* - node address 314* - operation type 315* - shape (ne) and strides (nb) 316* - source tensor addresses 317* - operation parameters 318* 319* @param cgraph The current ggml computation graph. 320* @return Pointer to the newly created ggml_cann_graph object. 321*/ 322static ggml_cann_graph * create_from_cgraph ( ggml_cgraph * cgraph) { 323ggml_cann_graph * new_graph = new ggml_cann_graph (); 324new_graph -> ggml_graph_properties . resize (cgraph -> n_nodes ); 325 326for ( int node_idx = 0 ; node_idx < cgraph -> n_nodes ; ++ node_idx) { 327ggml_tensor * node = cgraph -> nodes [node_idx]; 328auto & prop = new_graph -> ggml_graph_properties [node_idx]; 329 330prop. node_address = node -> data ; 331prop. node_op = node -> op ; 332prop. node_type = node -> type ; 333 334std :: copy_n (node -> ne , GGML_MAX_DIMS , prop. ne ); 335std :: copy_n (node -> nb , GGML_MAX_DIMS , prop. nb ); 336 337for ( int src = 0 ; src < GGML_MAX_SRC ; ++ src) { 338if (node -> src [src]) { 339prop. src_address [src] = node -> src [src] -> data ; 340prop. src_type [src] = node -> src [src] -> type ; 341std :: copy_n (node -> src [src] -> ne , GGML_MAX_DIMS , prop. src_ne [src]); 342std :: copy_n (node -> src [src] -> nb , GGML_MAX_DIMS , prop. src_nb [src]); 343} else { 344prop. src_address [src] = nullptr ; 345prop. src_type [src] = GGML_TYPE_COUNT ; 346std :: fill_n (prop. src_ne [src], GGML_MAX_DIMS , 0 ); 347std :: fill_n (prop. src_nb [src], GGML_MAX_DIMS , 0 ); 348} 349} 350 351memcpy (prop. op_params , node -> op_params , GGML_MAX_OP_PARAMS ); 352} 353 354return new_graph; 355} 356 357/** 358* @brief Check whether this CANN graph matches the given ggml computation graph. 359* 360* This function compares the number of nodes and each node's properties 361* (operation type, dimensions, strides, inputs, and operation parameters) 362* to determine whether this CANN graph matches the given ggml graph. 363* 364* @param cgraph The current ggml computation graph. 365* @return true if this CANN graph matches the ggml graph; false otherwise. 366*/ 367bool matches_cgraph ( ggml_cgraph * cgraph) { 368if (this -> ggml_graph_properties . size () != static_cast < size_t > (cgraph -> n_nodes )) { 369return false; 370} 371 372for ( int i = 0 ; i < cgraph -> n_nodes ; ++ i) { 373if (!this -> ggml_graph_properties [i]. has_matching_properties (cgraph -> nodes [i])) { 374return false; 375} 376} 377 378return true; 379} 380}; 381 382/** 383* @brief LRU cache for managing ggml_cann_graph objects. 384* 385* This class maintains a list of shared_ptr to ggml_cann_graph objects 386* and enforces a maximum capacity. It provides methods to push new graphs, 387* move existing graphs to the front (most recently used), and clear the cache. 388*/ 389struct ggml_cann_graph_lru_cache { 390size_t capacity ; /**< Maximum number of graphs in the cache. */ 391 392std :: list < ggml_cann_graph *> cache_list ; /**< List storing cached graphs as raw pointers. */ 393 394ggml_cann_graph_lru_cache() { capacity = parse_integer(get_env_as_lowercase(" GGML_CANN_GRAPH_CACHE_CAPACITY "). value_or (" 12 ")); } 395 396/** 397* @brief Push a new graph to the front of the cache. 398* If the cache exceeds capacity, the least recently used graph is deleted. 399* @param new_node Pointer to the new ggml_cann_graph to cache. 400* Ownership is transferred to the cache (cache will delete it). 401*/ 402void push ( ggml_cann_graph * new_node) { 403if (cache_list. size () >= capacity) { 404ggml_cann_graph * old = cache_list. back (); 405cache_list. pop_back (); 406delete old; // free the old graph 407} 408cache_list. push_front (new_node); 409} 410 411/** 412* @brief Clear all graphs from the cache (also frees memory). 413*/ 414void clear () { 415for (auto ptr : cache_list) { 416delete ptr; 417} 418cache_list. clear (); 419} 420 421/** 422* @brief Destructor that clears the cache and frees all cached graphs. 423*/ 424~ ggml_cann_graph_lru_cache () { clear(); } 425 426/** 427* @brief Find a cached CANN graph that matches the given ggml graph and move it to front. 428* 429* This function iterates through the cached CANN graphs stored in the LRU cache and 430* compares them against the given ggml computation graph. If a matching graph is found, 431* it is promoted to the front of the LRU cache and returned. Otherwise, the function 432* returns nullptr. 433* 434* @param cgraph The current ggml computation graph. 435* @return true if found; false otherwise. 436*/ 437bool find_and_move_to_front ( ggml_cgraph * cgraph) { 438for (auto & graph_ptr : this -> cache_list ) { 439if ( graph_ptr -> matches_cgraph ( cgraph )) { 440cache_list. remove ( graph_ptr ); 441cache_list. push_front (graph_ptr); 442return true; 443} 444} 445return false; 446} 447}; 448#endif // USE_ACL_GRAPH 449 450struct ggml_cann_rope_cache { 451~ ggml_cann_rope_cache () { 452if (theta_scale_cache) { 453ACL_CHECK (aclrtFree(theta_scale_cache)); 454} 455if (sin_cache) { 456ACL_CHECK ( aclrtFree (sin_cache)); 457} 458if (cos_cache) { 459ACL_CHECK ( aclrtFree (cos_cache)); 460} 461if (position_select_index) { 462ACL_CHECK ( aclrtFree (position_select_index)); 463} 464if (theta_scale_exp_host) { 465free (theta_scale_exp_host); 466} 467if (position_select_index_host) { 468free (position_select_index_host); 469} 470if (yarn_ramp_cache) { 471ACL_CHECK ( aclrtFree (yarn_ramp_cache)); 472} 473} 474 475bool equal ( int64_t theta_scale_length, 476int64_t position_length, 477float ext_factor, 478float theta_scale, 479float freq_scale, 480float attn_factor, 481bool is_neox, 482bool indep_sects, 483bool mrope_used, 484bool is_imrope, 485int sections[ 4 ]) { 486return this -> theta_scale_length == theta_scale_length && this -> position_length == position_length && 487this -> ext_factor == ext_factor && this -> theta_scale == theta_scale && this -> freq_scale == freq_scale && 488this -> attn_factor == attn_factor && this -> is_neox == is_neox && this -> indep_sects == indep_sects && 489this -> mrope_used == mrope_used && this -> is_imrope == is_imrope && this -> sections [ 0 ] == sections[ 0 ] && 490this -> sections [ 1 ] == sections[ 1 ] && this -> sections [ 2 ] == sections[ 2 ] && this -> sections [ 3 ] == sections[ 3 ]; 491} 492 493void set ( int64_t theta_scale_length, 494int64_t position_length, 495float ext_factor, 496float theta_scale, 497float freq_scale, 498float attn_factor, 499bool is_neox, 500bool indep_sects, 501bool mrope_used, 502bool is_imrope, 503int sections[ 4 ]) { 504this -> theta_scale_length = theta_scale_length; 505this -> position_length = position_length; 506this -> ext_factor = ext_factor; 507this -> theta_scale = theta_scale; 508this -> freq_scale = freq_scale; 509this -> attn_factor = attn_factor; 510this -> is_neox = is_neox; 511this -> indep_sects = indep_sects; 512this -> mrope_used = mrope_used; 513this -> is_imrope = is_imrope; 514this -> sections [ 0 ] = sections[ 0 ]; 515this -> sections [ 1 ] = sections[ 1 ]; 516this -> sections [ 2 ] = sections[ 2 ]; 517this -> sections [ 3 ] = sections[ 3 ]; 518} 519 520// memory cache, prepare before inferencing. 521void * theta_scale_cache = nullptr ; 522float * theta_scale_exp_host = nullptr ; 523int * position_select_index_host = nullptr ; 524void * position_select_index = nullptr ; 525void * yarn_ramp_cache = nullptr ; 526// sin/cos cache, used only to accelerate first layer on each device 527void * sin_cache = nullptr ; 528void * cos_cache = nullptr ; 529// Properties to check before reusing the sincos cache 530int64_t theta_scale_length = 0 ; 531int64_t position_length = 0 ; 532bool cached = false; 533float ext_factor = 0.0f ; 534float theta_scale = 0.0f ; 535float freq_scale = 0.0f ; 536float attn_factor = 0.0f ; 537bool is_neox = false; 538bool indep_sects = false; 539bool mrope_used = false; 540int sections[ 4 ] = { 0 , 0 , 0 , 0 }; 541bool is_imrope = false; 542}; 543 544struct ggml_cann_tensor_cache { 545~ ggml_cann_tensor_cache () { 546if (cache != nullptr ) { 547ACL_CHECK ( aclrtFree (cache)); 548} 549} 550 551void * cache = nullptr ; 552int64_t size = 0 ; 553}; 554 555/** 556* @brief Context for managing CANN backend operations. 557*/ 558struct ggml_backend_cann_context { 559int32_t device ; /**< Device ID. */ 560std :: string name ; /**< Name of the device. */ 561std :: string description ; /**< Description of the device. */ 562aclrtEvent copy_event = nullptr; /**< Event for managing copy operations. */ 563#ifdef USE_ACL_GRAPH 564/// Cached CANN ACL graph used for executing the current ggml computation graph. 565ggml_cann_graph_lru_cache graph_lru_cache ; 566bool acl_graph_mode = true; 567#endif 568bool async_mode ; 569// Rope Cache 570ggml_cann_rope_cache rope_cache ; 571// Constant Pool 572ggml_cann_tensor_cache rms_norm_one_tensor_cache ; 573ggml_cann_tensor_cache rms_norm_zero_tensor_cache ; 574 575aclrtStream streams [ GGML_CANN_MAX_STREAMS ] = { nullptr }; /**< Array of streams for the device. */ 576 577/** 578* @brief Constructor for initializing the context with a given device. 579* @param device Device ID. 580*/ 581explicit ggml_backend_cann_context ( int device) : device (device), name (" CANN " + std:: to_string ( device )) { 582ggml_cann_set_device ( device ); 583description = aclrtGetSocName (); 584 585#ifdef USE_ACL_GRAPH 586acl_graph_mode = parse_bool (get_env_as_lowercase(" GGML_CANN_ACL_GRAPH ").value_or("on")); 587GGML_LOG_INFO ( "%s: device %d execution mode is %s (%s)\n" , __func__, device, acl_graph_mode ? "GRAPH" : "EAGER" , 588acl_graph_mode ? "acl graph enabled" : "acl graph disabled" ); 589#endif 590} 591 592/** 593* @brief Destructor for cleaning up resources. 594*/ 595~ ggml_backend_cann_context () { 596ggml_cann_set_device (device); 597if (copy_event != nullptr ) { 598ACL_CHECK ( aclrtDestroyEvent (copy_event)); 599} 600for ( int i = 0 ; i < GGML_CANN_MAX_STREAMS ; ++ i) { 601if (streams[i] != nullptr ) { 602ACL_CHECK ( aclrtDestroyStream (streams[i])); 603} 604} 605} 606 607/** 608* @brief Get or create a stream for a given index. 609* @param stream Index of the stream. 610* @return The stream corresponding to the given index. 611*/ 612aclrtStream stream ( int stream) { 613if (streams[stream] == nullptr ) { 614// If the device is not set here, destroying the stream later may cause a mismatch 615// between the thread contexts where the stream was created and destroyed. 616// However, I printed the device_id, thread_id, and stream, and they are all consistent. 617ACL_CHECK ( aclrtSetDevice (device)); 618ACL_CHECK ( aclrtCreateStream ( & streams[stream])); 619} 620return streams[stream]; 621} 622 623/** 624* @brief Get or create the default stream (index 0). 625* @return The default stream. 626*/ 627aclrtStream stream () { return stream ( 0 ); } 628 629// TODO: each stream should have a memory pool. 630std ::unique_ptr < ggml_cann_pool > mem_pool; /**< Memory pool for the device. */ 631 632/** 633* @brief Create a new memory pool for a given device. 634* @param device Device ID. 635* @return A unique pointer to the new memory pool. 636*/ 637static std ::unique_ptr < ggml_cann_pool > new_pool_for_device ( int device); 638 639/** 640* @brief Get or create the memory pool for the context. 641* @return Reference to the memory pool. 642*/ 643ggml_cann_pool & pool () { 644if (mem_pool == nullptr ) { 645mem_pool = new_pool_for_device (device); 646} 647return * mem_pool; 648} 649}; 650 651#endif // CANN_COMMON_H