Prhub

#28091 [LoRA] Fix experimental fast-path multi-adapter correctness + flashinfer 0.6.12 compatibility

原始 PR 作者 jybsuper 合并时间 2026-06-20 07:20 文件变更 15 提交数 6 评论 3 代码增减 +229 / -60

执行摘要

修复实验 LoRA 多适配器正确性与 flashinfer 0.6.12 兼容

来自 issue #27329 的实验路径在 flashinfer 升级后出现编译失败,且用户报告多适配器时输出乱码。三个独立但都影响正确性的 bug 需要修复。具体问题包括:flashinfer 0.6.12 修改了内部 API;cuBLAS 快速路径错误地使用适配器槽 0;双流分配在 CUDA 图捕获时导致重用损坏。

此 PR 值得精读,尤其是双流重叠的设计权衡和 CUDA 图捕获的保护策略。展示了如何在不破坏性能的前提下修复并发正确性 bug。对于使用实验 LoRA 路径的团队必须合入,对于其他开发者可作为 CUDA 图安全的参考。

讨论亮点

无 Review 评论,仅两名 reviewer 批准。PR body 已详尽说明问题原因和修复方案。

实现拆解

  1. flashinfer 0.6.12 兼容:在 trtllm_fused_moe_kernel_launcher.cu 中新增 RoutingInputMode 枚举,调整 get_sf_out_offset_* 调用,新增 expertIds 参数传递为 nullptr,设置 supported_major_versions=[10, 12] 以支持 sm103。同时更新 runner.hfused_permute_quant.cuh 中符号调用。
  2. cuBLAS 路径单适配器限制:在 7 个 cuBLAS 分发点(sgemm_lora_asgemm_lora_bqkv_lora_bgate_up_lora_bkv_b_lora_absorbed×3)增加 weights.shape[0]==1 检查,多适配器时自动回退到 Triton 内核。
  3. 双流重叠分配提升:在 moe_overlap.pyfused_experts_none_to_experimental_sgl_trtllm_fp8_lora_two_stream 中,在 side-stream fork 前调用 merged_experts_fused_moe_lora_addstage='routing' 预布置路由缓存,并预分配 gate_up_lora_intermediate,使 side-stream 在 CUDA 图捕获时零分配。
  4. 共享加法图捕获保护:在 shared_add_overlap.pymaybe_overlap_staged_shared_add 中增加 torch.cuda.is_current_stream_capturing() 检测,捕获时禁止跨流 add_,回退到串行加法。
  5. 导入修复:将 _pack_topk_for_flashinfer_routed 替换为 fused_pack_topk,该函数已移入 jit_kernel/trtllm_lora_temp/topk_pack.py,影响 lora_dispatch.pysgl_fp8_moe.pymoe_overlap.py
文件 模块 状态 重要度
python/sglang/srt/lora/trtllm_lora_temp/moe_overlap.py 双流 LoRA modified 6.82
python/sglang/jit_kernel/trtllm_lora_temp/data/csrc/trtllm_fused_moe_kernel_launcher.cu JIT 内核 modified 5.39
python/sglang/srt/lora/trtllm_lora_temp/shared_add_overlap.py 共享叠加 modified 5.39
python/sglang/srt/lora/trtllm_lora_temp/triton_ops/virtual_experts.py 路由虚专家 modified 4.62

关键符号

fused_experts_none_to_experimental_sgl_trtllm_fp8_lora_two_stream maybe_overlap_staged_shared_add _get_routing fused_experts_none_to_experimental_sgl_trtllm_fp8_lora prepare_moe_common

关键源码片段

python/sglang/srt/lora/trtllm_lora_temp/moe_overlap.py core-logic

核心双流修复:提升路由分配至主流,预分配中间缓冲区,side-stream 仅启动内核,解决多适配器下 CUDA 图捕获崩溃

# 提升 side-chain 分配至主流,确保 CUDA 图安全
# 预布置路由缓存(stage="routing")并预分配 shrink intermediate
merged_experts_fused_moe_lora_add(
    output=gate_up_delta,
    hidden_states=hidden_states,
    lora_a=lora_info.gate_up_lora_a_weights,
    lora_b=lora_info.gate_up_lora_b_weights,
    topk_ids=topk_ids,
    topk_weights=topk_weights,
    token_lora_mapping=token_lora_mapping,
    mul_routed_weight=False,
    experts_shared_outer_loras_a=lora_info.experts_shared_outer_loras,
    experts_shared_outer_loras_b=False,
    routing_cache=fused_lora_routing_cache,
    stage="routing",
    local_expert_offset=quant_info.local_expert_offset,
    local_num_experts=quant_info.local_num_experts,
)
# 预分配 side-stream 所需的 intermediate buffer
gate_up_lora_intermediate = hidden_states.new_empty(
    (hidden_states.shape[0],
     topk_ids.shape[1],
     lora_info.gate_up_lora_a_weights.shape[2],
    )
)
python/sglang/srt/lora/trtllm_lora_temp/shared_add_overlap.py core-logic

增加 CUDA 图捕获检测,禁止跨流 shared-add 重叠,防止 replay 时 output 损坏

# 防止在 CUDA 图捕获期间进行跨流 add_
# 跨流 add_ 事件会损坏 output,因此回退到串行加法
if torch.cuda.is_current_stream_capturing():
    # 让模型层通过 unstage_shared_expert_add 回收 staged tensor
    # 在 current_stream.wait_stream(alt_stream) 之后安全执行加法
    return None

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

修复涉及实验路径(默认关闭),风险可控。但 JIT 内核编译依赖 flashinfer 版本,sm103 支持可能需额外验证。cuBLAS 路径限制单适配器可能引入小精度变化(多适配器回退到 Triton 路径,该路径已证明正确)。双流提升和 shared-add 保护仅影响捕获模式,不影响正常执行。无新增测试,需依赖现有 CI 覆盖。

影响范围限于使用 --moe-runner-backend experimental_sgl_trtllmSGLANG_EXPERIMENTAL_LORA_OPTI=1 的用户。修复后多适配器(≥2)输出正常,flashinfer 0.6.12+ 环境可编译,CUDA 图捕获下解码稳定。TP/EP>1 场景的崩溃问题消除。对于单适配器用户,cuBLAS 路径保持不变,性能无影响。

实验路径默认关闭 JIT 内核兼容性依赖 flashinfer 版本 无新增测试覆盖

关联 Issue

#27329 [LoRA] Experimental fast LoRA path with `experimental_sgl_trtllm` MoE backend for FP8 and NVFP4 models

完整报告

参与讨论