[BugFix] weight load bug when checkpoint expert.gate and exepert.up_proj are not fused (#13113)

Co-authored-by: yuechguo <yuechguo@amd.com>
This commit is contained in:
Morpheus Guo
2025-11-14 16:35:44 +08:00
committed by GitHub
parent 49141df94a
commit e7b57b0d04
3 changed files with 30 additions and 41 deletions

View File

@@ -32,6 +32,8 @@ if _is_cuda:
if _is_npu:
import torch_npu
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
from sglang.srt.distributed import (
split_tensor_along_last_dim,
tensor_model_parallel_all_gather,
@@ -55,10 +57,6 @@ ROTARY_EMBED_CLASSES = {
"normal": apply_rotary_pos_emb,
}
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
if _use_aiter:
from aiter import flash_attn_varlen_func as aiter_flash_attn_varlen_func
@dataclasses.dataclass
class SingletonCache:
@@ -348,8 +346,16 @@ class VisionAiterAttention(nn.Module):
self,
**kwargs,
):
if not _use_aiter:
if not _is_hip:
raise Exception("aiter_attn is only available for AMD")
try:
from aiter import flash_attn_varlen_func as aiter_flash_attn_varlen_func
except ImportError as e:
raise ImportError(
"aiter is AMD specific kernel library. Please make sure aiter is installed on your AMD device."
) from e
self.flash_attn_varlen_func = aiter_flash_attn_varlen_func
super().__init__()
def forward(
@@ -375,7 +381,7 @@ class VisionAiterAttention(nn.Module):
seq_lens = cu_seqlens[1:] - cu_seqlens[:-1]
max_seqlen = seq_lens.max().item()
return aiter_flash_attn_varlen_func(
return self.flash_attn_varlen_func(
q=q,
k=k,
v=v,
@@ -590,11 +596,11 @@ class VisionAttention(nn.Module):
backend = "fa3"
else:
backend = "triton_attn"
elif _use_aiter:
if get_device_capability() < (9, 4):
backend = "triton_attn"
else:
elif _is_hip:
if get_device_capability() >= (9, 4) and _use_aiter:
backend = "aiter_attn"
else:
backend = "triton_attn"
else:
backend = "sdpa"
if backend == "fa3" and is_blackwell():

View File

@@ -521,6 +521,11 @@ class FusedMoE(torch.nn.Module):
global_expert_location_metadata = get_global_expert_location_metadata()
if global_expert_location_metadata is None:
if not getattr(param, "_sglang_require_global_experts", False):
expert_id = self._map_global_expert_id_to_local_expert_id(expert_id)
if expert_id == -1:
return
self._weight_loader_impl(
param=param,
loaded_weight=loaded_weight,

View File

@@ -22,10 +22,6 @@ import torch
import torch.nn as nn
from sglang.srt.configs.qwen3_vl import Qwen3VLMoeConfig, Qwen3VLMoeTextConfig
from sglang.srt.distributed import (
get_moe_expert_parallel_world_size,
get_tensor_model_parallel_rank,
)
from sglang.srt.layers.moe.fused_moe_triton.layer import FusedMoE
from sglang.srt.layers.quantization.base_config import QuantizationConfig
from sglang.srt.model_executor.forward_batch_info import ForwardBatch, PPProxyTensors
@@ -127,34 +123,16 @@ def load_fused_expert_weights(
param = params_dict[name]
# weight_loader = typing.cast(Callable[..., bool], param.weight_loader)
weight_loader = param.weight_loader
ep_rank = get_tensor_model_parallel_rank()
ep_size = get_moe_expert_parallel_world_size()
if ep_size == 1:
for expert_id in range(num_experts):
curr_expert_weight = loaded_weight[expert_id]
weight_loader(
param,
curr_expert_weight,
name,
shard_id,
expert_id,
)
else:
experts_per_ep = num_experts // ep_size
start_expert = ep_rank * experts_per_ep
end_expert = (
(ep_rank + 1) * experts_per_ep if ep_rank != ep_size - 1 else num_experts
# let ep moe layer to gracefully handle expert_ids that do not belong to local moe rank
for expert_id in range(num_experts):
curr_expert_weight = loaded_weight[expert_id]
weight_loader(
param,
curr_expert_weight,
name,
shard_id,
expert_id,
)
for idx, expert_id in enumerate(range(start_expert, end_expert)):
curr_expert_weight = loaded_weight[expert_id]
weight_loader(
param,
curr_expert_weight,
name,
shard_id,
idx,
)
return True