char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
082b326fc
char/aliceai-t5-moe
1#include "ggml-et-kernels.h" 2 3#include "ggml-et-kernels-embed.hpp" 4#include "ggml-et-uberkernel-kernel-map.h" 5#include "ggml-impl.h" 6 7#include <cstdlib> 8#include <cstring> 9#include <fstream> 10 11#define ET_TRACE_DECODER_IMPL 12#include <et-trace/decoder.h> 13#include <et-trace/layout.h> 14 15static constexpr size_t GGML_ET_UBERKERNEL_PARAM_ALIGN = 64 ; 16 17static size_t ggml_et_align_up (size_t value ,size_t alignment ) { 18return (value + alignment - 1 )& ~(alignment - 1 ); 19} 20 21static size_t ggml_et_next_capacity (size_t current_capacity ,size_t required_capacity ) { 22if (current_capacity == 0 ) { 23return required_capacity ; 24 } 25 26size_t next_capacity = current_capacity ; 27while (next_capacity < required_capacity ) { 28next_capacity *=2 ; 29 } 30 31return next_capacity ; 32} 33 34static ggml_backend_et_uberkernel_slot & ggml_et_uberkernel_current_slot (ggml_backend_et_uberkernel_context * uk_ctx ) { 35return uk_ctx -> slots [uk_ctx -> current_slot ]; 36} 37 38// Wait for any in-flight launch that previously used this slot to finish, 39// so the host vectors and device buffers are safe to mutate / free. 40static void ggml_et_uberkernel_slot_wait (ggml_backend_et_uberkernel_slot & slot , 41const std::shared_ptr < rt::IRuntime > & runtime ) { 42if (!slot .has_pending || !runtime ) { 43return ; 44 } 45runtime -> waitForEvent (slot .pending_event ); 46slot .has_pending = false; 47} 48 49static void ggml_et_uberkernel_reset_segment (ggml_backend_et_uberkernel_context * uk_ctx ) { 50if (!uk_ctx ) { 51return ; 52 } 53 54uk_ctx -> shire_mask = 0 ; 55auto & slot = ggml_et_uberkernel_current_slot (uk_ctx ); 56// Drain any prior launch on this slot before clearing its host buffers. 57// begin_graph and abort_graph both come through here; in either case we 58// must not yank the source memory out from under an in-flight DMA. 59ggml_et_uberkernel_slot_wait (slot ,ggml_et_runtime ()); 60slot .insts .clear (); 61slot .params_blob .clear (); 62} 63 64static bool ggml_et_uberkernel_ensure_slot_capacity (ggml_backend_et_uberkernel_slot & slot , 65ggml_backend_et_device_context * dev_ctx , 66size_t insts_size , 67size_t params_size ) { 68 std::shared_ptr < rt::IRuntime > runtime = ggml_et_runtime (); 69if (!dev_ctx || !runtime ) { 70return false; 71 } 72 73try { 74if (slot .device_insts == nullptr || insts_size > slot .device_insts_capacity ) { 75const size_t new_capacity = ggml_et_next_capacity (slot .device_insts_capacity ,insts_size ); 76if (slot .device_insts ) { 77runtime -> freeDevice (dev_ctx -> rtid ,slot .device_insts ); 78 } 79slot .device_insts = runtime -> mallocDevice (dev_ctx -> rtid ,new_capacity ); 80slot .device_insts_capacity = slot .device_insts ?new_capacity :0 ; 81 } 82 83if (slot .device_params == nullptr || params_size > slot .device_params_capacity ) { 84const size_t new_capacity = ggml_et_next_capacity (slot .device_params_capacity ,params_size ); 85if (slot .device_params ) { 86runtime -> freeDevice (dev_ctx -> rtid ,slot .device_params ); 87 } 88slot .device_params = runtime -> mallocDevice (dev_ctx -> rtid ,new_capacity ); 89slot .device_params_capacity = slot .device_params ?new_capacity :0 ; 90 } 91 }catch (const std::exception & e ) { 92GGML_LOG_ERROR ("ET: Failed to resize uberkernel buffers: %s\n" ,e .what ()); 93return false; 94 } 95 96return slot .device_insts != nullptr && slot .device_params != nullptr ; 97} 98 99// Get embedded kernel data by name 100static std::vector < std::byte > ggml_et_get_embedded_kernel (const std::string & kernel_name ) { 101auto it = ggml_et_embedded_kernels .find (kernel_name ); 102if (it == ggml_et_embedded_kernels .end ()) { 103GGML_LOG_ERROR ("ET: Unknown embedded kernel: %s\n" ,kernel_name .c_str ()); 104return {}; 105 } 106 107const unsigned char * data = it -> second .first ; 108uint64_t size = it -> second .second ; 109 110 std::vector < std::byte > buffer (size ); 111 std::memcpy (buffer .data (),data ,size ); 112 113return buffer ; 114} 115 116// Read kernel from file (for development/override) 117static std::vector < std::byte > ggml_et_read_kernel_file (const std::string & kernel_path ) { 118 std::ifstream file (kernel_path , std::ios::binary | std::ios::ate ); 119if (!file ) { 120return {}; 121 } 122 123auto size = file .tellg (); 124file .seekg (0 , std::ios::beg ); 125 126 std::vector < std::byte > buffer (size ); 127file .read (reinterpret_cast < char *> (buffer .data ()),size ); 128 129return buffer ; 130} 131 132// Load kernel from file or embedded data 133bool ggml_et_load_kernel (ggml_backend_et_device_context * dev_ctx ,const std::string & kernel_name ) { 134 std::shared_ptr < rt::IRuntime > runtime = ggml_et_runtime (); 135if (!runtime ) { 136GGML_LOG_ERROR ("ET: Runtime not available for kernel loading\n" ); 137return false; 138 } 139 140// Check if kernel already loaded 141if (dev_ctx -> loaded_kernels .find (kernel_name )!= dev_ctx -> loaded_kernels .end ()) { 142GGML_LOG_DEBUG ("ET: Kernel %s already loaded on device %d\n" ,kernel_name .c_str (),dev_ctx -> devidx ); 143return true; 144 } 145 146 std::vector < std::byte > kernel_data ; 147const char * kernels_path = getenv ("GGML_ET_KERNELS_PATH" ); 148 149// If GGML_ET_KERNELS_PATH is set, try to load from file first 150if (kernels_path ) { 151 std::string kernel_file = std::string (kernels_path )+ "/" + kernel_name + ".elf" ; 152kernel_data = ggml_et_read_kernel_file (kernel_file ); 153 154if (!kernel_data .empty ()) { 155GGML_LOG_INFO ("ET: Loading kernel %s from file: %s\n" ,kernel_name .c_str (),kernel_file .c_str ()); 156 }else { 157GGML_LOG_INFO ("ET: Kernel file not found: %s, falling back to embedded\n" ,kernel_file .c_str ()); 158 } 159 } 160 161// If no file data, use embedded kernel 162if (kernel_data .empty ()) { 163kernel_data = ggml_et_get_embedded_kernel (kernel_name ); 164if (kernel_data .empty ()) { 165GGML_LOG_ERROR ("ET: Failed to get kernel data for %s\n" ,kernel_name .c_str ()); 166return false; 167 } 168 } 169 170try { 171// Load kernel code using device's default stream 172auto load_result = runtime -> loadCode (dev_ctx -> default_stream ,kernel_data .data (),kernel_data .size ()); 173runtime -> waitForEvent (load_result .event_ ); 174 175// Store kernel handle 176dev_ctx -> loaded_kernels [kernel_name ]= load_result .kernel_ ; 177return true; 178 179 }catch (const std::exception & e ) { 180GGML_LOG_ERROR ("ET: Failed to load kernel %s: %s\n" ,kernel_name .c_str (),e .what ()); 181return false; 182 } 183} 184 185static bool ggml_et_launch_kernel_internal (ggml_backend_et_device_context * dev_ctx , 186const std::string & kernel_name , 187void * params , 188size_t params_size , 189uint64_t shire_mask , 190bool enable_print , 191bool sync_error_check , 192 rt::EventId * out_event = nullptr ) { 193 std::shared_ptr < rt::IRuntime > runtime = ggml_et_runtime (); 194if (!runtime ) { 195GGML_LOG_ERROR ("ET: Runtime not available for kernel launch\n" ); 196return false; 197 } 198 199// Lazy loading: check if kernel is loaded, load if needed 200auto kernel_it = dev_ctx -> loaded_kernels .find (kernel_name ); 201if (kernel_it == dev_ctx -> loaded_kernels .end ()) { 202// Kernel not loaded - load it 203if (!ggml_et_load_kernel (dev_ctx ,kernel_name )) { 204GGML_LOG_ERROR ("ET: Failed to lazy-load kernel %s\n" ,kernel_name .c_str ()); 205return false; 206 } 207 208// Update iterator after successful load 209kernel_it = dev_ctx -> loaded_kernels .find (kernel_name ); 210if (kernel_it == dev_ctx -> loaded_kernels .end ()) { 211GGML_LOG_ERROR ("ET: Kernel %s not found after loading\n" ,kernel_name .c_str ()); 212return false; 213 } 214 } 215 216 rt::KernelId kernel_id = kernel_it -> second ; 217 218try { 219// Setup kernel launch options 220 rt::KernelLaunchOptions k_opts ; 221k_opts .setShireMask (shire_mask );// Default: all shires (0xFFFFFFFF) 222k_opts .setBarrier (true);// Wait for completion 223k_opts .setFlushL3 (false);// No L3 flush needed 224if (enable_print ) { 225k_opts .setUserTracing (reinterpret_cast < uint64_t > (dev_ctx -> trace_buffer ), 226static_cast < uint32_t > (ET_TRACE_BUFFER_SIZE ), 2270 ,// threshold 228shire_mask ,// shire mask 2290xFFFFFFFFFFFFFFFFULL ,// threadMask - all threads 2300xFFFFFFFFU ,// eventMask - all events 2310xFFFFFFFFU // filterMask - all levels 232 ); 233 } 234 235if (sync_error_check ) { 236runtime -> waitForStream (dev_ctx -> default_stream ); 237auto errors = runtime -> retrieveStreamErrors (dev_ctx -> default_stream ); 238if (!errors .empty ()) { 239GGML_LOG_ERROR ("ET: Errors detected before kernel \"%s\" launch\n" ,kernel_name .c_str ()); 240for (const auto & error :errors ) { 241GGML_LOG_ERROR ("ET: Error code: %d\n" , (int )error .errorCode_ ); 242 } 243abort (); 244 } 245 } 246 247 rt::EventId launch_event = runtime -> kernelLaunch (dev_ctx -> default_stream ,kernel_id , 248reinterpret_cast < std::byte *> (params ),params_size ,k_opts ); 249if (out_event ) { 250* out_event = launch_event ; 251 } 252 253if (enable_print ) { 254 std::vector < std::byte > host_trace_buf (ET_TRACE_BUFFER_SIZE ); 255runtime -> memcpyDeviceToHost (dev_ctx -> default_stream ,dev_ctx -> trace_buffer ,host_trace_buf .data (), 256ET_TRACE_BUFFER_SIZE ); 257runtime -> waitForStream (dev_ctx -> default_stream ); 258const auto * trace_header = reinterpret_cast < const trace_buffer_std_header_t *> (host_trace_buf .data ()); 259const trace_entry_header_t * entry = nullptr ; 260while ((entry = Trace_Decode (trace_header ,entry ))) { 261if (entry -> type != TRACE_TYPE_STRING ) { 262continue ; 263 } 264const auto * str_entry = reinterpret_cast < const trace_string_t *> (entry ); 265printf ("[hart %d] %s" ,entry -> hart_id ,str_entry -> string ); 266 } 267 } 268 269if (sync_error_check ) { 270// Already triggered. No need to retrigger 271if (!enable_print ) { 272runtime -> waitForStream (dev_ctx -> default_stream ); 273 } 274auto errors = runtime -> retrieveStreamErrors (dev_ctx -> default_stream ); 275if (!errors .empty ()) { 276GGML_LOG_ERROR ("ET: Errors detected during kernel \"%s\" execution\n" ,kernel_name .c_str ()); 277for (const auto & error :errors ) { 278GGML_LOG_ERROR ("ET: Error code: %d\n" , (int )error .errorCode_ ); 279 } 280abort (); 281 } 282 } 283 284return true; 285 }catch (const std::exception & e ) { 286GGML_LOG_ERROR ("ET: Failed to launch kernel %s: %s\n" ,kernel_name .c_str (),e .what ()); 287return false; 288 } 289} 290 291void ggml_et_uberkernel_begin_graph (ggml_backend_et_uberkernel_context * uk_ctx ) { 292if (!uk_ctx ) { 293return ; 294 } 295 296uk_ctx -> failed = false; 297ggml_et_uberkernel_reset_segment (uk_ctx ); 298} 299 300static bool ggml_et_launch_uberkernel_segment (ggml_backend_et_device_context * dev_ctx , 301ggml_backend_et_uberkernel_context * uk_ctx ) { 302if (!uk_ctx || !dev_ctx ) { 303return false; 304 } 305 306auto & slot = ggml_et_uberkernel_current_slot (uk_ctx ); 307if (slot .insts .empty ()) { 308return true; 309 } 310 311 std::shared_ptr < rt::IRuntime > runtime = ggml_et_runtime (); 312if (!runtime ) { 313GGML_LOG_ERROR ("ET: Runtime not available for uberkernel commit\n" ); 314uk_ctx -> failed = true; 315return false; 316 } 317 318const size_t insts_size = slot .insts .size ()* sizeof (ggml_et_uberkernel_inst ); 319const size_t params_size = slot .params_blob .size (); 320const uint64_t shire_mask = uk_ctx -> shire_mask ; 321bool ok = false; 322 323try { 324if (!ggml_et_uberkernel_ensure_slot_capacity (slot ,dev_ctx ,insts_size ,params_size )) { 325GGML_LOG_ERROR ("ET: Failed to allocate uberkernel device buffers\n" ); 326uk_ctx -> failed = true; 327// Drop this segment but keep the slot drained so we don't leak 328// host vectors into the next graph. 329slot .insts .clear (); 330slot .params_blob .clear (); 331uk_ctx -> shire_mask = 0 ; 332return false; 333 } 334 335// Fire-and-forget H2D + launch on default_stream. In-stream FIFO 336// ordering guarantees the kernel sees fully-uploaded buffers; the 337// host source bytes (slot.insts / slot.params_blob) stay alive 338// because we won't touch this slot again until pending_event fires. 339runtime -> memcpyHostToDevice (dev_ctx -> default_stream ,reinterpret_cast < const std::byte *> (slot .insts .data ()), 340slot .device_insts ,insts_size , true); 341runtime -> memcpyHostToDevice (dev_ctx -> default_stream ,slot .params_blob .data (),slot .device_params ,params_size , 342 true); 343 344ggml_et_uberkernel_params params = { 345static_cast < uint32_t > (slot .insts .size ()), 346static_cast < uint32_t > (sizeof (ggml_et_uberkernel_inst )), 347reinterpret_cast < uint64_t > (slot .device_insts ), 348reinterpret_cast < uint64_t > (slot .device_params ), 349 }; 350 351 rt::EventId launch_event {}; 352ok = ggml_et_launch_kernel_internal (dev_ctx ,"uberkernel" ,& params ,sizeof (params ),shire_mask , false, false, 353& launch_event ); 354if (ok ) { 355// The kernelLaunch above is the last thing on default_stream 356// that touches this slot's device buffers. Recording its event 357// lets the next reuse of this slot wait on that one event 358// instead of the whole stream. 359slot .pending_event = launch_event ; 360slot .has_pending = true; 361 } 362 }catch (const std::exception & e ) { 363GGML_LOG_ERROR ("ET: Failed to commit uberkernel segment: %s\n" ,e .what ()); 364 } 365uk_ctx -> failed = !ok ; 366 367if (ok ) { 368uk_ctx -> current_slot = (uk_ctx -> current_slot + 1 ) % ggml_backend_et_uberkernel_context::SLOT_COUNT ; 369auto & next = ggml_et_uberkernel_current_slot (uk_ctx ); 370ggml_et_uberkernel_slot_wait (next ,runtime ); 371next .insts .clear (); 372next .params_blob .clear (); 373 }else { 374slot .insts .clear (); 375slot .params_blob .clear (); 376 } 377uk_ctx -> shire_mask = 0 ; 378return ok ; 379} 380 381void ggml_et_uberkernel_abort_graph (ggml_backend_et_uberkernel_context * uk_ctx ) { 382if (!uk_ctx ) { 383return ; 384 } 385 386uk_ctx -> failed = false; 387ggml_et_uberkernel_reset_segment (uk_ctx ); 388} 389 390bool ggml_et_uberkernel_failed (const ggml_backend_et_uberkernel_context * uk_ctx ) { 391return uk_ctx && uk_ctx -> failed ; 392} 393 394static bool ggml_et_launch_uberkernel (ggml_backend_et_device_context * dev_ctx , 395const std::string & kernel_name , 396void * params , 397size_t params_size , 398uint64_t shire_mask , 399bool enable_print , 400bool sync_error_check ) { 401if (!dev_ctx ) { 402return false; 403 } 404 405ggml_backend_et_uberkernel_context * uk_ctx = & dev_ctx -> uberkernel ; 406const uint16_t uberkernel_id = ggml_et_uberkernel_kernel_id_from_name (kernel_name .c_str ()); 407if (uberkernel_id == GGML_ET_UBERKERNEL_KERNEL_INVALID ) { 408if (!ggml_et_launch_uberkernel_segment (dev_ctx ,uk_ctx )) { 409return false; 410 } 411return ggml_et_launch_kernel_internal (dev_ctx ,kernel_name ,params ,params_size ,shire_mask ,enable_print , 412sync_error_check ); 413 } 414 415auto & slot = ggml_et_uberkernel_current_slot (uk_ctx ); 416const size_t params_offset = ggml_et_align_up (slot .params_blob .size (),GGML_ET_UBERKERNEL_PARAM_ALIGN ); 417if (params_offset > slot .params_blob .size ()) { 418slot .params_blob .resize (params_offset ); 419 } 420 421const std::byte * params_bytes = reinterpret_cast < const std::byte *> (params ); 422slot .params_blob .insert (slot .params_blob .end (),params_bytes ,params_bytes + params_size ); 423 424ggml_et_uberkernel_inst inst = { 425uberkernel_id , 4260 , 427static_cast < uint32_t > (params_offset ), 428static_cast < uint32_t > (params_size ), 429 }; 430slot .insts .push_back (inst ); 431 432if (slot .insts .size ()== 1 ) { 433uk_ctx -> shire_mask = shire_mask ; 434 } 435 436return true; 437} 438 439bool ggml_et_uberkernel_end_graph (ggml_backend_et_device_context * dev_ctx ) { 440if (!dev_ctx || !dev_ctx -> uberkernel_enabled ) { 441return true; 442 } 443 444return ggml_et_launch_uberkernel_segment (dev_ctx ,& dev_ctx -> uberkernel ); 445} 446 447bool ggml_et_launch_kernel (ggml_backend_et_device_context * dev_ctx , 448const std::string & kernel_name , 449void * params , 450size_t params_size , 451uint64_t shire_mask , 452bool enable_print , 453bool sync_error_check ) { 454if (!dev_ctx ) { 455return false; 456 } 457 458if (!dev_ctx -> uberkernel_enabled ) { 459return ggml_et_launch_kernel_internal (dev_ctx ,kernel_name ,params ,params_size ,shire_mask ,enable_print , 460sync_error_check ); 461 } 462 463return ggml_et_launch_uberkernel (dev_ctx ,kernel_name ,params ,params_size ,shire_mask ,enable_print , 464sync_error_check ); 465} 466 467void ggml_et_unload_kernel (ggml_backend_et_device_context * dev_ctx ,const std::string & kernel_name ) { 468 std::shared_ptr < rt::IRuntime > runtime = ggml_et_runtime (); 469if (!runtime ) { 470return ; 471 } 472 473auto kernel_it = dev_ctx -> loaded_kernels .find (kernel_name ); 474if (kernel_it != dev_ctx -> loaded_kernels .end ()) { 475try { 476runtime -> unloadCode (kernel_it -> second ); 477dev_ctx -> loaded_kernels .erase (kernel_it ); 478 }catch (const std::exception & e ) { 479GGML_LOG_ERROR ("ET: Failed to unload kernel %s: %s\n" ,kernel_name .c_str (),e .what ()); 480 } 481 } 482} 483 484void ggml_et_unload_all_kernels (ggml_backend_et_device_context * dev_ctx ) { 485if (!dev_ctx ) { 486return ; 487 } 488 489// Make a copy of kernel names since ggml_et_unload_kernel modifies the map 490 std::vector < std::string > kernel_names ; 491kernel_names .reserve (dev_ctx -> loaded_kernels .size ()); 492for (const auto & kernel_pair :dev_ctx -> loaded_kernels ) { 493kernel_names .push_back (kernel_pair .first ); 494 } 495 496for (const auto & kernel_name :kernel_names ) { 497ggml_et_unload_kernel (dev_ctx ,kernel_name ); 498 } 499} 500 501std::vector < std::pair < std::string , rt::KernelId >> ggml_et_get_loaded_kernels (ggml_backend_et_device_context * dev_ctx ) { 502 std::vector < std::pair < std::string , rt::KernelId >> loaded_kernels ; 503loaded_kernels .reserve (dev_ctx -> loaded_kernels .size ()); 504for (const auto & kernel_pair :dev_ctx -> loaded_kernels ) { 505loaded_kernels .push_back (kernel_pair ); 506 } 507return loaded_kernels ; 508}