Files
project_6/ixformer_sdk/train/speedformer/policy/utils.py
project6-dev 87a19d2d00 feat(CRITICAL): 从 GitHub 扫描搬运 ixformer SDK + xllm 完整 GDN/MoE 代码
来源:
  1. Chranos/ixformer (GitHub) → ixformer_sdk/ (230 files, 70K lines)
     - inference/functions/vllm.py: vllm_moe_topk_softmax 完整实现 (2033 lines)
     - inference/functions/moe.py: MoE ops 完整实现 (1380 lines)
     - contrib/vllm_flash_attn/: FA2 Python 接口 (1018 lines)
     - contrib/tgi/fused_moe.py: TGI fused MoE (429 lines)
     - csrc/include/ixformer/: C++ kernel headers + cmake

  2. Deep-Spark/xllm (GitHub) → upstream_ref/xllm_latest/ (+15 files)
     - npu_torch/qwen3_5_decoder_layer_impl.cpp/.h
     - npu_torch/qwen3_5_gated_delta_net.cpp/.h
     - npu_torch/qwen3_next_*.cpp/.h (6 files)
     - npu_torch/attention.cpp/.h + fused_moe.cpp/.h + CMakeLists.txt
     - models/llm/qwen3_5.h + qwen3_5_mtp.h + qwen3_next.h
     - models/vlm/qwen3_5.h

调用链完整性:
  ixformer_sdk/inference/functions/vllm.py
    → ops.infer.moe_topk_softmax() (C++ 层)
    → 这就是 base 镜像 libixformer.so 里的实现

  upstream_ref/xllm_latest/core/layers/ilu/fused_moe.cpp
    → ixformer::infer::topk_softmax() (直接 C++ 调用)
    → ixformer::infer::group_gemm() → 完整 7-step MoE pipeline
2026-08-11 02:32:06 +00:00

157 lines
5.3 KiB
Python

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any, Callable, Dict, List, Optional, Union
import re
import torch
import torch.nn as nn
@dataclass
class SubModuleReplacementDescription:
r"""
Describe how a submodule will be replaced
Args:
suffix (str): used to get the submodule object
target_module (ParallelModule): specifies the module class used to replace to submodule
kwargs (Dict[str, Any]): the dictionary used to pass extra arguments to the `ParallelModule.from_native_module` method.
ignore_if_not_exist (bool): if the submodule does not exist, ignore it or raise an exception
"""
suffix: str
target_module: nn.Module
kwargs: Dict[str, Any] = None
ignore_if_not_exist: bool = False
@dataclass
class ModulePolicyDescription:
"copy from colossalai, for now sub_module_replacement and method_replacement is used"
r"""
Describe how the attributes and parameters will be transformed in a policy.
Args:
attribute_replacement (Dict[str, Any]): key is the attribute name, value is the attribute value after sharding
param_replacement (List[Callable]): a list of functions to perform in-place param replacement. The function
must receive only one arguments: module. One example is
```python
def example_replace_weight(module: torch.nn.Module):
weight = module.weight
new_weight = shard_rowwise(weight, process_group)
module.weight = torch.nn.Parameter(new_weight)
```
sub_module_replacement (List[SubModuleReplacementDescription]): each element in the list is a SubModuleReplacementDescription
object which specifies the module to be replaced and the target module used to replacement.
method_replace (Dict[str, Callable]): key is the method name, value is the method for replacement
"""
attribute_replacement: List[Dict[str, Any]] = None
param_replacement: List[Callable] = None
sub_module_replacement: List[SubModuleReplacementDescription] = None
method_replacement: List[Dict[str, Callable]] = None
def getattr_(obj, attr: str, ignore: bool = False):
r"""
Get the object's multi sublevel attr
Args:
obj (object): The object to set
attr (str): The multi level attr to set
ignore (bool): Whether to ignore when the attr doesn't exist
"""
attrs = attr.split(".")
for a in attrs:
try:
obj = get_obj_list_element(obj, a)
except AttributeError:
if ignore:
return None
raise AttributeError(
f"Object {obj.__class__.__name__} has no attribute {attr}")
return obj
def get_obj_list_element(obj, attr: str):
r"""
Get the element of the list in the object
If the attr is a normal attribute, return the attribute of the object.
If the attr is a index type, return the element of the index in the list, like `layers[0]`.
Args:
obj (Object): The object to get
attr (str): The suffix of the attribute to get
"""
re_pattern = r"\[\d+\]"
prog = re.compile(re_pattern)
result = prog.search(attr)
if result:
matched_brackets = result.group()
matched_index = matched_brackets.replace("[", "")
matched_index = matched_index.replace("]", "")
attr_ = attr.replace(matched_brackets, "")
container_obj = getattr(obj, attr_)
obj = container_obj[int(matched_index)]
else:
obj = getattr(obj, attr)
return obj
def setattr_(obj, attr: str, value, ignore: bool = False):
r"""
Set the object's multi sublevel attr to value, if ignore, ignore when it doesn't exist
Args:
obj (object): The object to set
attr (str): The multi level attr to set
value (Any): The value to set
ignore (bool): Whether to ignore when the attr doesn't exist
"""
attrs = attr.split(".")
for a in attrs[:-1]:
try:
obj = get_obj_list_element(obj, a)
except AttributeError:
if ignore:
return
raise AttributeError(
f"Object {obj.__class__.__name__} has no attribute {attr}")
set_obj_list_element(obj, attrs[-1], value)
def set_obj_list_element(obj, attr: str, value):
r"""
Set the element to value of a list object
It used like set_obj_list_element(obj, 'layers[0]', new_layer), it will set obj.layers[0] to value
Args:
obj (object): The object to set
attr (str): the string including a list index like `layers[0]`
"""
re_pattern = r"\[\d+\]"
prog = re.compile(re_pattern)
result = prog.search(attr)
if result:
matched_brackets = result.group()
matched_index = matched_brackets.replace("[", "")
matched_index = matched_index.replace("]", "")
attr_ = attr.replace(matched_brackets, "")
container_obj = getattr(obj, attr_)
container_obj[int(matched_index)] = value
else:
setattr(obj, attr, value)
def print_rank_0(message):
if torch.distributed.is_initialized():
if torch.distributed.get_rank() == 0:
print(message, flush=True)
else:
print(message, flush=True)