Expand description
Startup-static PEFT LoRA adapter: remap/validate/pack into the fixed-address rank-padded pool. v0 = one adapter, slot 0, always on.
NAMING: everything here is Peft*/adapter_*/Lora* (adapter sense) —
kv_lora_rank/q_lora_rank (atlas-core/src/config.rs:182-207) are MLA
vocabulary, not this.
NOTE on leaks: the intermediate WeightStore device copies of the
unpadded A/B tensors become garbage after pool packing and are never
freed (no dealloc on weight structs anywhere in Atlas). Accepted at
holo adapter scale (~tens of MiB).
SDD facade: the surface is split by functional seam into types (the
module/AB enums + weight/slot structs + LoraWeights impl), slot_math
(pure slot/offset placement + routing), key (classify + adapter identity),
env (the $ATLAS_LORA_* hatches + validate_peft_config), and loading
(audit/pack + the load entry points). Every public name re-exports at its
own visibility so crate::lora::X / spark_model::lora::X paths are stable.
Modules§
- rdma_
stage - RDMA LoRA staging (spark-model half): turn a peer-staged adapter’s manifest
into a set of pool-slot LANDING TARGETS (the only place
classify_key+ the per-slot offset math live), then drivespark_storage::RdmaLoraLoaderto RDMA-load the adapter’s A/B straight into a resident slot for fast rotation. Landing is byte-identical to the disk pack (the loader does the same F16/F32→BF16 convert + B row-repack).
Structs§
- Adapter
Slot - One packed pool slot: a resident adapter’s own name/config + its per-layer
pairs (a/b DevicePtrs into that slot’s byte sub-region of the shared pool).
layersis GLOBAL-layer-indexed (len = num_hidden_layers), the same index the install walk uses. - Embed
Overlay - Stage-2 compact result for one adapter slot’s embed overlay.
rowsholds then_overridereplacement embedding rows in ascending-idsorder;slot_mapis the[vocab]i32 lookup (-1default,[id] = compact-row-index) the embed kernel indexes by token id.lmheadisSomeonly for an UNTIED head that ships its own overlay tensors. - Expert
Lora Layer - One MoE layer’s routed-expert LoRA coverage: a SPARSE map keyed by
(expert_index, projection). Real adapters adapt a subset of the (up to 512) experts, so a denseVec<[LoraPair; 3]>sizednum_expertswould waste storage and force a 512-wide static walk; the map only holds the packed pairs.LoraPairisCopy, so the whole struct is cheap toCloneon install. - Expert
Work - One expert’s contiguous sorted-row range (the grouped-GEMM row block for
that expert).
rows == 0experts are dropped by the planner. - LmHead
Overlay - Distinct output-projection overlay for an untied lm_head. Rows are recomputed
into logits by a
dot(hidden, row)per overridden id (noslot_map). - Lora
Adapter Input - One adapter to pack, for the multi-adapter entry point.
storeis the adapter’s on-device BF16WeightStore(host F16/F32→BF16 already done byspark_runtime::weights::adapter::load_adapter_safetensors). - Lora
Layer Weights - One full-attention layer’s adapted modules.
None= module not adapted. Pairs are the CANONICALLoraPairfromlayers::ops::lora_delta(Copy — installed by copy into the layer structs at model build). - Lora
Weights - The loaded adapter set: one fixed-address rank-padded pool holding up to
max_lorasequal-size slots, oneAdapterSlotper resident adapter, and per-module[max_loras]device u64 pointer tables (the frozen M2 BGMV contract — filled index k for each packed slot, NULL for the rest). - Overlay
Raw - Stage-1 raw upload: the adapter’s own overlay tensors copied into owned
device scratch (the source
WeightStoreis freed after the loader). Dims are recorded so Stage 2 can shape the row-diff and compaction without the store.embed_base/lmhead_basealso carry amodules_to_savefull-weight replacement (row-diff finds the changed rows either way). - Overlay
RawSlot - Stage-1 raw upload + the (host) clamped trainable ids the delta rows align to.
- Overlay
Tensor - A classified overlay tensor: its target embedding and its role.
- Overlay
Tensors - Tensor names the loader has collected for one adapter, partitioned by
(module, role).
Option<String>= the safetensors key, filled at most once. - Slot
View - Task #27: a per-slot snapshot for the pure victim-selection policy. Taken on
the model thread at a scheduler-quiescent point (the only place
ref_countis authoritative), then handed toselect_victim_slot. - Token
Overlay Set - The resolved overlay set for the whole adapter pool. Built once in
set_lora_weights(Stage 2) from the per-slotEmbedOverlays.Noneon the model ⇒ overlay feature OFF ⇒ every forward hook early-returns (byte-identical to a no-overlay build).
Enums§
- Adapter
Ab - Expert
Proj - Which routed-expert projection a delta targets. Ordered so
BTreeMap<(u16, ExpertProj), _>has a stable, testable key order. - Lora
Module - Lora
Target - The decoded target of one PEFT LoRA tensor.
Attnkeeps the existing denseLoraModulepath byte-identical;Router/Expertare the Feature-1 additions routed into per-layerExpertLoraLayer/ router storage. - Overlay
Module - Which tied embedding an overlay tensor belongs to.
- Overlay
Tensor Kind - The role an overlay tensor plays in
build_overlay. - Victim
Error - Why a promotion cannot find a victim slot.
Constants§
- ROWDIFF_
THRESH - Rows whose max abs difference from the served embed table exceeds this are
treated as “overridden” by a
modules_to_save/baked base_layer. Clears bf16 rounding noise (matching rows land ≤0.05; a real differing row ≥1.3).
Functions§
- adapter_
id_ hash - Stable u64 identity for an adapter, derived from its human NAME (never the runtime pool slot index, which is reused across swap/rotation). Task #24: this is the cache-identity key that keeps the KV/prefix cache adapter-correct so a request reuses ONLY blocks computed under the same adapter.
- allow_
partial_ targets ATLAS_LORA_ALLOW_PARTIAL=1— load an adapter that names target modules Atlas cannot apply, skipping those and applying the rest.- apply_
expert_ lora_ sorted - Fold
proj’s per-expert LoRA deltas onto the SORTED grouped-GEMM output. - apply_
router_ lora - Fold the router (
mlp.gate) LoRA delta onto the routing logits in place, BEFORE top-k.router_in=[n, hidden],gate_logits=[n, num_experts](modified in place). Chunked bymax_rows(the scratch capacity in rows). - build_
moe_ row_ adapter_ decode - SOLID Incr-4 (batched decode fold): build the per-row
[padded_n]i32 adapter map the device-side MoE gather-BGMV fold reads. One token per sequence at decode, so a per-row map IS a per-seq map (notop_kexpansion — the kernel indexesrow_adapter[row / top_k]). - build_
moe_ row_ adapter_ host - Build the
[total_tokens]per-packed-row adapter map for the device-side grouped fold.cu_seqlens_hostis the[batch + 1]prefix-sum of per-stream token counts (the packing SSOT);adapter_slots[b]is streamb’sadapter_slot. Each stream’s slot is broadcast across its[cu_seqlens_host[b], cu_seqlens_host[b + 1])row span. A base stream (adapter_slot < 0) writes-1(device kernel skips those rows); a stream deferring to the active adapter would resolve< 0 → activeat the call site before this, so a genuine base row is a real-1here (distinct base sentinel — seelora-solid.md§6). - build_
overlay - Stage 2 (
set_lora_weights): row-diff against the served tables, compact the override rows, build theslot_map, and free the Stage-1 raw scratch.Ok(None)when the slot overrides nothing (silently inert = correct). - build_
override_ set - Union of (rows that differ from the served base) and (trainable ids), sorted
ascending and deduped. This is the final set of vocab rows the overlay
replaces.
row_diff[i]= rowiof the adapter base differs from served. - build_
seq_ slot_ host - Build the per-step
seq_slot[padded_n]host buffer the batched bgmv reads, from each real sequence’sadapter_slot. Resolution rules (graph-safe: contents vary per step, buffer address is fixed): real row i (< n):adapter_slots[i]if>= 0, elseactive— a request with noadapterfield carries-1and DEFERS to the installed active adapter, so a single global adapter (or a rotate re-point) applies to every default row exactly like the n==1 path. pad row i (n..padded_n):-1— base / no delta (bgmv early-returns). A row that explicitly names the base model (some future-1-means-base convention) is out of scope here;-1uniformly means “defer to active”. - clamp_
trainable_ to_ vocab - Clamp
trainableids to the served vocab, preserving list order (the delta tensor’s rows align positionally to it). - classify_
key - PEFT key → (layer, module, A|B). Every unsupported shape is a NAMED
hard rejection — never a skip. Prefix-agnostic on purpose: the Holo
base checkpoint keys are
model.language_model.layers.{i}.*(weight_prefix auto-detected server-side), but a PEFT trainer wrapping the text trunk emitsmodel.layers.{i}.*; both carry the layer index right after “.layers.”. - classify_
overlay_ key - Classify a PEFT adapter tensor as a token-overlay tensor, or
Noneif it is an ordinarylora_A/lora_Bweight (whichsuper::classify_keyhandles). - ensure_
decode_ route_ servable - SOLID Incr-4 host-side pre-lookup guard for the BATCHED decode entries
(
decode_batch_compute_main,mixed_forward): a batch containing a row routed to a NON-active adapter (Refuse) cannot be served by the single-active fold —build_moe_row_adapter_decodedefensively maps such rows to base, so proceeding would SILENTLY serve base weights for an adapter-routed request. Call BEFORE any graph lookup/capture so capturedpadded_ngraphs stay route-agnostic. Pure (noself, no GPU) so the decision is unit-testable without hardware. - expert_
delta_ workitems - PURE: from the base MoE
expert_offsetsprefix-sum ([num_experts + 1],expert_offsets[e]..expert_offsets[e+1]= experte’s sorted rows) and the adapter’s adapted-expert set, produce the (expert, row_off, rows) work-items for the delta side-path. Experts with zero routed rows or a malformed offset pair are skipped (never a panic). This is the correctness-critical mapping and is unit-tested without a GPU. - expert_
router_ bytes - Pure padded-byte estimator for the (separate) expert/router pool, used by the
VRAM preflight and pinned by a golden unit test — mirrors
super::pool_slot_bytesbut over the audited routed-expert + router key set (real adapters target a SUBSET, so this is sized from the audit, never fromnum_experts × num_layersmaxima). Per (layer, expert, proj) and per router layer:(stride·in + out·stride)·2BF16 bytes, wherestrideis the DERIVED uint4-alignedexpert_pack::packed_strideofmax_rank— the same derivation the pack loop uses (SSOT), so sizing and packing agree byte-for-byte even at a non-multiple-of-8 rank cap. - full_
attention_ layers - is_
gdn_ key - Whether
keynames a GDN / linear-attention tensor — the familyclassify_keyrejects outright. - load_
lora_ adapters_ generic - Single-adapter convenience wrapper (packs slot 0 only) — byte-identical to
the pre-multi-adapter path. Kept for the unit tests and any single-adapter
caller. The
nameis stamped onto the sole slot. - load_
lora_ adapters_ multi - Model-agnostic MULTI-adapter PEFT load: audit every adapter, VRAM-preflight
the N-slot pool, pack each adapter into its slot (0..N-1), and build the
per-module
[max_loras]pointer tables (index k filled per packed slot, rest NULL). One resident adapter is byte-identical to the single-adapter path (slot 0,offstarts at 0). - lora_
eager_ env - Permanent LoRA debugging hatch:
ATLAS_LORA_EAGER=1(ortrue) forces eager decode (no CUDA-graph capture) when an adapter is active, so graph-vs-eager output parity can be compared in the field. Read ONCE — the decode graph gate runs per token. Resolved at the point of use rather than cached in a static: the model carries this asModelLevers::lora_eagerfor the per-token decode gate, and the remaining callers are one-shot startup checks where a getenv is free. - lora_
experts_ env - Feature-1 (MoE expert + router LoRA) master switch.
ATLAS_LORA_EXPERTS=1(ortrue) opts INTO loading + applying routed-expert / router deltas. DEFAULT OFF: an adapter that targetsmlp.experts.*/mlp.gateis a NAMED reject at load unless this is set, so the base path stays byte-identical and the (correctness-first, host-synced, non-graphable) expert side-path is never silently on. Read once. - lora_
peer_ env $ATLAS_LORA_PEER(host:port of anatlas-weight-peerstaging a rotation set) — when set, arms rotation (eager decode) even for a single resident slot, because an RDMA swap re-points that slot in place. Unset = disk path only, byte-identical to today.- lora_
rotate_ env ATLAS_LORA_ROTATE=1(ortrue) ARMS runtime adapter rotation: it forces eager decode (no CUDA-graph capture) so aset_active_lorare-point is immediately live (eager-on-rotate — the graph would otherwise replay the previously-captured slot pointers). A pool with >1 resident adapter arms this automatically (seeTransformerModel::lora_rotatable), so this env is only needed to arm rotation on a SINGLE resident adapter (e.g. RDMA slot-swap-in-place). Unset + a single startup adapter = today’s behaviour exactly (graphs ON, slot-0 pointers baked). Seelora_eager_envon why this is not cached.- max_
lora_ expert_ rank - Feature-1 padded expert/router LoRA rank cap (
ATLAS_LORA_EXPERT_RANK, default 16). Separate from--max-lora-rank(the attention pool) because the per-(layer,expert,proj) pool grows ~num_experts × num_layersfaster, so a low cap bounds the expert-pool VRAM blow-up. An adapter withrabove this is a named reject. - no_
batch_ verify ATLAS_LORA_NO_BATCH_VERIFY=1— restore the old refusal of cross-sequence batched speculative verify while a LoRA adapter is resident.- override_
source - Where an overridden id’s replacement row comes from:
Some(k)= trainable delta rowk(delta WINS when an id is both trainable and baked-different);None= the adapter’s bakedbase_layer[id]. - pack_
store_ into_ slot - Runtime disk swap: audit + pack an already-loaded adapter
storeinto an EXISTING poolslotoflw, in place, and stamp that slot’s name/config/layers. Byte-identical to a startup pack of the same adapter into that slot — same audit, A-contiguous copy, and B row-repack viapack_slot. The slot sub-region is re-zeroed first (a reused slot still holds the prior adapter’s bytes, and pad rows/cols must stay 0 for padded-K correctness). Returns the rebuilt per-layer pairs so the caller can re-install them if the slot is currently active. Like the startup pack, the intermediatestore’s device copies leak (small, one-off per swap). Used for the pool-size-1 dynamic-load demo (load a different adapter into the single slot at runtime). - prefill_
bgmv_ forced ATLAS_LORA_PREFILL_BGMV=1— force prefill LoRA through the per-row BGMV instead of the tensor-core GEMM.- reject_
pending_ overlay - Feature 2 load gate, called from the loader once overlay tensors are
collected. The device-side overlay apply is now WIRED (Stage-1
super::overlay_build::stage_overlay_rawupload → Stage-2super::overlay_build::build_overlayrow-diff/compact → theembed_tokens/lm_headforward hooks incrate::model::token_overlay), sotrainable_tokens/modules_to_save{embed_tokens, lm_head}tensors are LOADED rather than rejected. - resolve_
moe_ lora_ route - Resolve the Feature-1 MoE-LoRA fold decision for a single-request pass.
- routed_
prefill_ slot_ of - #30 (routed-prefill precision): the pure predicate behind
LoraWeights::routed_prefill_slot, split out for unit testing. Resolves a request’sadapter_slot(>= 0→ that slot,-1→ active) and returnsSome(resolved)ONLY when it routes to a NON-active, in-range slot. ReturnsNonefor an active/base request (byte-identical installed-pair path) and for out-of-range slots. Kept in exact lockstep withupload_seq_slot_uniform(resolved == active→DevicePtr(0)). - router_
dims - (out_dim, in_dim) of the base router (
mlp.gate) projection:[num_experts, hidden]. A router LoRA perturbs the pre-selection routing logits. - select_
routed_ pair - #30 (routed-prefill precision): pure selector for a routed prefill’s
(global_layer, module)
LoraPairout of a request slot’s GLOBAL-layer-indexedlayers.Nonewhen the index is out of range, the layer is unadapted, or the routed adapter does not adapt that module (the caller then falls back to the bgmv/installed path — no delta if the slot’s a_table cell is base). GPU-free + unit-tested so the (layer, module) indexing is verifiable without hardware. - select_
victim_ slot - Task #27 pure victim-selection policy over the CACHE region only (the caller
passes
(slot_index, view)for slots[pinned, max_loras)— pinned startup adapters are never candidates, so the resident set and its position-based resolver can never desync). Tiers: - stage_
overlay_ raw - Stage 1 (loader): upload the classified overlay tensors of one adapter into
owned device scratch.
Ok(None)when the adapter ships no overlay tensors.embed_full/lmhead_full(modules_to_save) map onto the*_baseslot. - validate_
peft_ config - Adapter-config gates that need build-time context (
--max-lora-rank). Parse-time gates (peft_type/DoRA/bias/regex target_modules/…) already ran inatlas_core::config::parse_peft_adapter_config.