nx_lora_pool.nx
buildroot/runtime/nx_lora_pool.nx
about
nx_lora_pool.nx -- H9 Multi-LoRA adapter pool (bits-up).
Per NISHI_ELDER_AI_OFF_DOCKER_2026_05_20.md ยง2.1 H9: serve hundreds
of fine-tuned adapters from a single base model. Punica / S-LoRA
ship this at scale -- one VRAM-resident backbone, N small
LoRA-rank adapters (rank 4..64), per-request adapter selection
at batch step time.
V1 mechanics: a fixed pool of NxLoraAdapter records keyed by
caller-supplied adapter_id. Each adapter carries opaque A/B
tensor pointers (the substrate doesn't need to know the tensor
shape to schedule routing; the consumer that runs the forward
pass knows). A refcount tracks how many active batch slots /
pending requests currently reference each adapter, so evict()
can refuse while the adapter is in flight.
Composition path:
- register_adapter once when the adapter is loaded to disk/VRAM
- acquire(id) when admit()ing a batch slot that wants the adapter
- release(id) when the batch slot transitions DONE
- evict(id) only when refcount drops to zero (cold-swap window)
The lookup is linear over n_loaded (V1 honest scope: pool size
stays small enough -- NX_LORA_POOL_MAX_ADAPTERS = 128 -- that
linear scan beats a hash table on the substrate's allocation
model; V2 can promote to open-addressed hash if profile demands).
Pure substrate logic. No Linux features. Composes with shipped
nx_batch_scheduler (each batch slot will eventually carry an
adapter_id field threading through admit/step/complete).
V1 honest scope:
- Adapter ID is i64 caller-supplied (no auto-allocation in V1)
- Allowed LoRA ranks are sealed-enum: 4, 8, 16, 32, 64
- Tensor data layout is OPAQUE to this primitive (A_data / B_data
are *i64 pointers the consumer dereferences with its own
shape knowledge; this matches how H1 nx_kv_arena treats
per-page payload bytes)
- alpha is stored as Q16 fixed-point (scale * 65536) to keep
this primitive integer-only at the substrate layer
dependencies 1 imports · 2 importers
imports: nx_syscalls.nx
imported by: nx_hackers_algo_compose_test.nxnx_lora_pool_test.nx
structs
| 115 | struct NxLoraAdapter |
| 127 | struct NxLoraPool |
consts
| 70 | const NX_MAGIC_65536: i64 = 65536 |
| 73 | const NX_LORA_POOL_MAX_ADAPTERS: i64 = 128 |
| 76 | const NX_LORA_RANK_4: i64 = 4 |
| 77 | const NX_LORA_RANK_8: i64 = 8 |
| 78 | const NX_LORA_RANK_16: i64 = 16 |
| 79 | const NX_LORA_RANK_32: i64 = 32 |
| 80 | const NX_LORA_RANK_64: i64 = 64 |
| 92 | const NX_LORA_OK: i64 = 0 |
| 93 | const NX_LORA_BAD_INPUT: i64 = 1 |
| 94 | const NX_LORA_NOT_FOUND: i64 = 2 |
| 95 | const NX_LORA_DUPLICATE: i64 = 3 |
| 96 | const NX_LORA_FULL: i64 = 4 |
| 97 | const NX_LORA_IN_USE: i64 = 5 |
| 98 | const NX_LORA_BAD_RANK: i64 = 6 |
| 99 | const NX_LORA_TAMPER: i64 = 7 |
| 100 | const NX_LORA_N_VERDICTS: i64 = 8 |
| 109 | const NX_LORA_ADAPTER_CANARY_PRE: i64 = 0x4C6F526141647072 // "LoRaAdpr" |
| 110 | const NX_LORA_ADAPTER_CANARY_POST: i64 = 0x4164707241646E64 // "AdprAdnd" |
| 111 | const NX_LORA_POOL_CANARY_PRE: i64 = 0x4C6F5261506F6F6C // "LoRaPool" |
| 112 | const NX_LORA_POOL_CANARY_POST: i64 = 0x506F6F6C456E6464 // "PoolEndd" |
functions
| 82 | func nx_lora_rank_is_valid(r: i64) -> i64 |
| 102 | func nx_lora_verdict_is_valid(v: i64) -> i64 called by 1: main |
| 136 | func nx_lora_adapter_is_valid(a: *NxLoraAdapter) -> i64 |
| 146 | func nx_lora_pool_is_valid(p: *NxLoraPool) -> i64 |
| 158 | func nx_lora_pool_new(max_adapters: i64) -> *NxLoraPool |
| 179 | func nx_lora__find_slot(p: *NxLoraPool, adapter_id: i64) -> i64 |
| 199 | func nx_lora_register(p: *NxLoraPool, adapter_id: i64, rank: i64, n_layers: i64, a_data: *i64, b_data: *i64, alpha_q16: i64) -> i64 |
| 229 | func nx_lora_lookup(p: *NxLoraPool, adapter_id: i64) -> *NxLoraAdapter |
| 238 | func nx_lora_acquire(p: *NxLoraPool, adapter_id: i64) -> i64 |
| 251 | func nx_lora_release(p: *NxLoraPool, adapter_id: i64) -> i64 |
| 267 | func nx_lora_evict(p: *NxLoraPool, adapter_id: i64) -> i64 |
| 286 | func nx_lora_n_loaded(p: *NxLoraPool) -> i64 |
| 291 | func nx_lora_refcount(p: *NxLoraPool, adapter_id: i64) -> i64 |
| 300 | func nx_lora_adapter_rank(a: *NxLoraAdapter) -> i64 |
| 305 | func nx_lora_adapter_n_layers(a: *NxLoraAdapter) -> i64 |
| 310 | func nx_lora_adapter_alpha_q16(a: *NxLoraAdapter) -> i64 |
| 315 | func nx_lora_adapter_id(a: *NxLoraAdapter) -> i64 |