code wiki / (root) / nx_gguf_load_lazy.nx

nx_gguf_load_lazy.nx source

↩ module page · 119 lines · 4698 B

1// nx_gguf_load_lazy.nx -- Phase B of conductor arc. 2// 3// L4.5 brick. Composes nx_placement.nx (Phase A) with nx_gguf_load.nx 4// to provide a ZERO-RAM-FOOTPRINT tensor handle: load a GGUF tensor 5// by name and get back an NxPlacedTensor in lazy (MMAP) placement. 6// The dequantized Q10 i64 storage is NOT allocated until the caller 7// invokes nx_placed_tensor_get / nx_placed_tensor_materialize. 8// 9// Honest architectural property (NOT a perf claim): 10// Each lazy handle is 88 bytes regardless of underlying tensor 11// size. At LOAD time the substrate holds the model as 88 * 12// n_tensors bytes of typed handles (e.g. ~25 KB for a Llama-7B 13// shape) without dequantizing anything. Materialization happens 14// per-tensor at first compute access; demote releases the 15// dequantized buffer back to the lazy state. 16// 17// This is semantically similar to llama.cpp's mmap + per-block 18// dequant-on-demand pattern. The structural difference: our handle 19// is a typed primitive a future conductor (Phase C dispatcher / Phase 20// D arbiter) can route, evict, and tier-promote. llama.cpp's lazy 21// dequant is in the matmul kernel internals, not exposed. 22// 23// NOT a claim: 24// - "lazy = smaller VRAM than CUDA" -- depends on working-set 25// and dispatcher; lazy alone proves nothing about peak RAM 26// - "lazy = faster than llama.cpp" -- llama.cpp's mmap path 27// achieves the same architectural property by a different name 28// - Any "Nx less RAM" ratio without measurement against a real 29// workload on real hardware 30// 31// Composition: 32// nx_placement.nx -- NxPlacedTensor + lifecycle 33// nx_gguf.nx -- header + tensor_info walker 34// nx_gguf_load.nx -- existing per-tensor canonical loader 35// (composed for materialization path) 36// 37// genealogy_id: numpy_memmap_pattern + huggingface_safetensors_lazy 38// lineage_id: substrate_gguf_lazy_loader_v1_conductor_phase_b 39 40// nx_safety_envelope: 41// intended_use: "Load a named GGUF tensor as a zero-RAM 42// lazy NxPlacedTensor; caller materializes 43// on demand" 44// sil_target: SIL2 45// asil_target: QM 46// dal_target: DAL C 47// evidence: [conductor_cardinal_2026-05-19, 48// composes_phase_a_proven, composes_existing_loaders] 49// hazard_register: [bug-tape-buf-freed-while-lazy-ref-held] 50// residual_risk: "Caller must keep gguf_buf alive as long 51// as any lazy ref exists" 52// verdict: NOT_YET_EVALUATED 53 54import "nx_syscalls.nx" 55import "nx_tier.nx" 56import "nx_tensor.nx" 57import "nx_gguf.nx" 58import "nx_gguf_load.nx" 59import "nx_placement.nx" 60 61// ===== Public: lazy load by name ================================== 62// 63// Same lookup semantics as nx_gguf_load_tensor; returns a lazy 64// NxPlacedTensor instead of materialized NxTensor. 65// 66// out_err verdicts: 67// NX_GL_OK on success 68// NX_GL_ERR_NOT_FOUND on miss 69// NX_GL_ERR_BAD_SHAPE on zero-element tensor 70 71func nx_gguf_load_tensor_lazy(buf: *u8, hdr: *NxGgufHeader, 72 name: *u8, name_len: nx_int, 73 out_err: *i64) -> *NxPlacedTensor { 74 let idx: nx_int = nx_gguf_find_tensor(hdr, name, name_len) 75 if idx < 0 { 76 out_err[0] = NX_GL_ERR_NOT_FOUND 77 return 0 as *NxPlacedTensor 78 } 79 let ti: *NxGgufTensorInfo = nx_gguf_tensor_at(hdr, idx) 80 81 let nv: i64 = nx_gguf_tensor_n_values(ti) 82 if nv <= 0 { 83 out_err[0] = NX_GL_ERR_BAD_SHAPE 84 return 0 as *NxPlacedTensor 85 } 86 87 // Shape buffer for the placement struct. 88 let shape: *i64 = sys_mmap(4 * 8) as *i64 89 shape[0] = ti.dim_0 90 shape[1] = ti.dim_1 91 shape[2] = ti.dim_2 92 shape[3] = ti.dim_3 93 94 let data_off: i64 = hdr.data_off + ti.offset 95 96 let p: *NxPlacedTensor = nx_placed_tensor_new_lazy( 97 buf, data_off, 98 ti.ggml_type, nv, 99 shape, ti.n_dims) 100 101 out_err[0] = NX_GL_OK 102 return p 103} 104 105// ===== Convenience: report lazy-handle footprint ================= 106// 107// Returns the total bytes the lazy handles consume. Each 108// NxPlacedTensor is NX_PT_STRUCT_BYTES = 88 bytes regardless of the 109// underlying tensor size. 110// 111// This is a STRUCTURAL FACT about the handle representation, NOT a 112// perf claim against any other framework. Comparisons to CUDA / 113// PyTorch / llama.cpp peak RAM require running both on the same 114// model + workload + hardware and measuring -- the lazy-handle size 115// alone proves nothing about end-to-end resource use. 116 117func nx_gguf_lazy_handle_bytes(n_tensors: nx_int) -> i64 { 118 return n_tensors * NX_PT_STRUCT_BYTES 119}