Repository navigation
[Fix] lora: Load fused-module members into their own buffer slots - #44332
Merged
yueming-yuan merged 4 commits intoOct 15, 2026
Merged
Conversation
yueming-yuan
requested review from
Fridge003,
Ying1123,
jybsuper,
lifuhuang and
yushengsu-thu
as code owners
October 14, 2026 20:15
An adapter may target any subset of q/k/v, gate/up, q_a/kv_a_with_mqa or Inkling wq/wk/wv/wr. The loader used to concatenate members into the fused key and failed (KeyError / ValueError) when one was absent. Each member now writes its own A rows and B rows of the fused buffer; absent members stay zero. The LoRA wrappers own the per-member TP geometry. MoE gate/up keeps the stacked path.
yueming-yuan
force-pushed
the
yueming/lora-fill-absent-fused-members
branch
from
October 14, 2026 22:06
e9b7cec to
4b86318
Compare
PEFT can ship an untrained up_proj as zero-element tensors. The dense gate/up normalization used to zero-fill them; per-member loading sliced them instead and raised IndexError.
CI collection requires an executable __main__ block in every registered test file. Also correct the subset test's docstring: k/v-only adapters raised ValueError rather than being dropped.
This was referenced Oct 19, 2026
nv-hwoo
pushed a commit
to nv-hwoo/sglang
that referenced
this pull request
Oct 20, 2026
…ir own buffer slots (sgl-project#44332)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
An adapter may target any subset of the members SGLang packs into one fused LoRA module:
q_proj/k_proj/v_proj->qkv_proj,gate_proj/up_proj->gate_up_proj,q_a_proj/kv_a_proj_with_mqa->fused_qkv_a_proj_with_mqa, Inklingwq_du/wk_dv/wv_dv/wr_du->qkvr. The loader concatenated the members into the fused key at normalization time, assuming specific members are present. On Qwen3-0.6B withsglang-miles:KeyError: ...self_attn.v_proj.lora_A.weightValueError: Cannot find target module nameValueError: Cannot find target module nameA trainer could only work around this by exporting zero A/B pairs for untrained members, with widths computed from its own copy of the engine's layout.
Modifications
Members are no longer concatenated in
LoRAAdapter. The memory pool writes each member into its own slot of the fused buffer:igoes to rows[i*r, (i+1)*r); B: memberigoes to the member's row range of the local output. Absent members are left zero, so the fused module computes exactly the partial adapter.first_output_dim) comes from the*WithLoRAwrapper that already owns the fused layout:lora_b_member_full_rows(),lora_b_member_local_offsets(),slice_lora_b_member().slice_lora_b_weightsis rebuilt from the same methods, so there is one definition per wrapper.packed_modules_mappingis not used; it is absent on Llama/Qwen2/Qwen3 and does not match the LoRA modules on Qwen3.5 / NemotronH.LORA_FUSED_MEMBERSinlora/utils.pyis the single member table;params_mappingandstacked_rankderive from it.qkv_proj,fused_qkv_a_proj_with_mqa, ...) is split by the same geometry; carrying both the fused and the per-member form is rejected.Behavior: an adapter covering all members loads byte-identical buffers to the old concatenating loader (unit test, all TP ranks,
max_lora_rank= r and r+1). Partial adapters that raised before now load. An MLA adapter with a fusedfused_qkv_a_proj_with_mqakey is newly accepted.Tests
test/registered/unit/lora/test_lora_fused_member_load.py(CPU, 37 cases) on fake QKV / MergedColumn / Inkling qkvr / MLA wrappers:sglang-miles@4076a68579), every TP rank,max_lora_rankin {r, r+1}LoRAAdapterkeeps dense members separate and still stacks expert gate/upE2E on H200, Qwen3-0.6B, r=8: each adapter is compared against the same SGLang running the PEFT-merged weights (
merge_and_unload). Mean |logprob diff|, rows = LoRA run, columns = merged model:The diagonal is bf16 rounding of the merged weights; every LoRA run matches only its own merged model. The full adapter's logprobs are identical (
==) tosglang-milesbefore this change.Not in this PR
Fused modules whose members are not plain row blocks of B, and MoE gate/up, keep the current path: GDN
in_proj_qkvz/in_proj_ba, Mambain_proj, routed/shared-expertgate_up_proj.Consumer
radixark/miles#4101 drops the trainer-side zero-fill and exports only the trained members.
CI States
Latest PR Test (Base): ❌ Run #38660217031
Latest PR Test (Extra): ❌ Run #38660216994
Latest PR Test (AMD ROCm 10): ❌ Run #38660217049