Expand description
2026-09-25: Runtime LoRA delta y += scale * (x @ A^T) @ B^T on BF16 activations: the single-adapter path and the per-request routed path.
Owner: model-layers ops. Invariants:
- Both stages contract at the pool’s padded rank
max_rank, never at the adapter’s rank; the pool is zeroed before packing, so the pad rows of A and pad columns of B are zero (lora/loading.rs). - The launchers here only launch kernels: they allocate nothing and do not synchronize.
apply_lora_deltareturns without launching whenMETRALE_LORA_NO_APPLY=1.
Structs§
- Lora
Attn Weights - 2026-09-25: Per-layer attention LoRA weights, installed by copy onto
Qwen3AttentionLayer. - Lora
FfnWeights - 2026-09-25: Per-layer dense-FFN LoRA weights, installed by copy onto
DenseFfnLayer. - Lora
Kernels - 2026-09-25: The kernel handles the LoRA launchers use, resolved when an adapter is installed.
Module names follow the
[modules]table of kernels/gb10/common/KERNEL.toml (dense_gemv_bf16.cuisgemv,dense_gemm_tc.cuisgemm_tc,dense_gemm_bf16.cuisgemm);residual_add,lora_bgmv,moe_lora_grouped_downandmoe_lora_gather_bgmvare file stems. - Lora
Pair - 2026-09-25: One adapted module, with the PEFT tensors in their own layouts, which are the
[N, K]weight layout the dense kernels expect: a:[max_rank, k_in]row-major BF16 (PEFTlora_A[r, in_features]in the firstrankrows, zero rows after); b:[n_out, max_rank]row-major BF16 (PEFTlora_B[out_features, r]in the firstrankcolumns of each row, zero columns after).scaleislora_alpha / r, orlora_alpha / sqrt(r)withuse_rslora, from the adapter’s config, whereuse_rslorais required (config/src/parsers/lora.rs). It is applied in the fold, not folded into B. - Lora
Route - 2026-09-25: Per-(layer, module) routing tables that
apply_lora_bgmvreads: the[max_loras]device tables of A and B pool addresses (a_table/b_table, 0 = the slot does not adapt this module), the[max_loras]f32scale_table, and the projection dims. The addresses are fixed when the pool is packed, so the adapter for each row is chosen only by the per-stepseq_slotbuffer. Installed by copy onto the layer next to the activeLoraPair, which the unrouted path uses.
Functions§
- apply_
lora_ bgmv - 2026-09-25: Per-request routed LoRA delta over
nrows, each naming its adapter slot inseq_slot[n](i32; a negative slot gets no delta):out[i, :] += scale_s * (x[i, :] @ A_s^T) @ B_s^Twiths = seq_slot[i]. - apply_
lora_ delta - 2026-09-25:
base_out[m, n_out] += scale * (x[m, k_in] @ a^T) @ b^Tfor oneLoraPair. - lora_
gemv_ max_ m - 2026-09-25: Row count at or below which
apply_lora_deltarunsmsingle-row GEMV deltas instead of one GEMM:METRALE_LORA_GEMV_MAX_M, read once per process, default 48 when unset or unparsable.dense_gemm_tctiles 16 rows (TC_TMin dense_gemm_tc.cu) and reads all of B whatevermis, so a smallmpays full B traffic for a partly empty tile. - lora_
no_ apply - 2026-09-25:
METRALE_LORA_NO_APPLYequal to"1", read once per process: keep the adapter resident but skip everyapply_lora_delta. A measurement lever that separates the cost of applying an adapter from the cost of having one loaded; the output is the base model’s while it is set. - lora_
no_ ffn - 2026-09-25:
METRALE_LORA_NO_FFNequal to"1", read once per process: the dense-FFN (dense_ffn.rs) and GDN out_proj (qwen3_ssm/lora.rs) skip their deltas, and the attention deltas still apply. A measurement lever; the output is wrong while it is set.