Files
project_6/ixformer_sdk/inference/functions/mm.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

316 lines
11 KiB
Python

import ixformer._C as ops
import torch
import torch.nn.functional
__all__ = [
"mm",
"addmm",
"fused_addmm_bias_col_act",
"ref_fused_addmm_bias_col_act",
"ref_addmm",
"ref_mm",
"ref_bmm",
"bmm",
]
def ref_mm(input, mat, *, out=None):
out = torch.mm(input, mat, out = out)
return out
def mm(input, mat, *, out=None):
"""
Args:
input: (m,k) torch.float16, torch.bfloat16, torch.float32
mat: (k,n) torch.float16, torch.bfloat16, torch.float32
out: (m,n) torch.float16, torch.bfloat16, torch.float32
Returns:
out: (m,n) torch.float16, torch.bfloat16, torch.float32
"""
assert input.dim() == mat.dim(), "mm tensors must be 2-D"
assert input.size(1) == mat.size(
0
), f"mm cannot be multiplied, {input.size(0)}X{input.size(1)} and {mat.size(0)}X{mat.size(1)}"
m = input.shape[0]
n = mat.shape[-1]
if out is None:
out = input.new_empty([m, n])
ops.infer.mm(input, mat, out)
return out
"""ixinfer support activations
/// @ingroup GEMM
typedef enum {
CUINFER_BLAS_GEMM_CUSTOM_NONE = 0,
CUINFER_BLAS_GEMM_CUSTOM_BIAS_ADD_ROW_OUT = 1,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS = 2,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_GELU = 3,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_RELU = 4,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_TRANSPOSE = 5,
CUINFER_BLAS_GEMM_CUSTOM_FLOATBIAS = 6,
CUINFER_BLAS_GEMM_CUSTOM_FLOATBIAS_GELU = 7,
CUINFER_BLAS_GEMM_CUSTOM_FLOATBIAS_RELU = 8,
CUINFER_BLAS_GEMM_CUSTOM_FLOATBIAS_TRANSPOSE = 9,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_SIGMOID = 10,
CUINFER_BLAS_GEMM_CUSTOM_FLOATBIAS_SIGMOID = 11,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_SILU = 12,
CUINFER_BLAS_GEMM_CUSTOM_FLOATBIAS_SILU = 13,
CUINFER_BLAS_GEMM_CUSTOM_SIGMOID = 14,
CUINFER_BLAS_GEMM_CUSTOM_SILU = 15,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_TANH = 16,
CUINFER_BLAS_GEMM_CUSTOM_FLOATBIAS_TANH = 17,
CUINFER_BLAS_GEMM_SPECIAL_INT8_FLOATBIAS = 18,
CUINFER_BLAS_GEMM_SPECIAL_INT8_FLOATBIAS_GELU = 19,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_SWISH = 20,
CUINFER_BLAS_GEMM_CUSTOM_HALFBIAS_ERF_GELU = 21
} cuinferGEMMCustomOption_t;
"""
activation_to_id = {
"fused_bias_col": 2, # support bf16, fp16
"fused_bias_gelu": 3, # support fp16
"fused_bias_relu": 4, # support fp16
}
id_to_activation = {value: key for key, value in activation_to_id.items()}
def ref_addmm(input, mat1, mat2, *, beta=1, alpha=1, out=None):
output_pt = torch.addmm(input, mat1, mat2, alpha=alpha, beta=beta)
return output_pt
def ref_fused_addmm_bias_col_act(
input, mat1, mat2, *, beta=1, alpha=1, out=None, bias=None, activation=2
):
if isinstance(activation, int):
assert activation in id_to_activation
if isinstance(activation, str):
assert activation in activation_to_id
activation = activation_to_id[activation]
if activation == 2:
output_pt = torch.addmm(input, mat1, mat2, alpha=alpha, beta=beta) + bias
elif activation == 3:
output_pt = torch.nn.functional.gelu(
torch.addmm(input, mat1, mat2, alpha=alpha, beta=beta) + bias
)
else:
output_pt = torch.nn.functional.relu(
torch.addmm(input, mat1, mat2, alpha=alpha, beta=beta) + bias
)
return output_pt
def addmm(input, mat1, mat2, *, beta=1, alpha=1, out=None):
"""
Args:
input: (m,n) torch.float16, torch.bfloat16, torch.float32
mat1: (m,k) torch.float16, torch.bfloat16, torch.float32
mat2: (k,n) torch.float16, torch.bfloat16, torch.float32
beta: float
alpha: float
out: (m,n) torch.float16, torch.bfloat16, torch.float32
Returns:
out: (m,n) torch.float16, torch.bfloat16, torch.float32
"""
assert mat1.dim() == mat2.dim(), "addmm mat1 mat2 tensors must be 2-D"
assert mat1.size(1) == mat2.size(
0
), f"addmm cannot be multiplied, {mat1.size(0)}X{mat1.size(1)} and {mat2.size(0)}X{mat2.size(1)}"
m = mat1.shape[0]
n = mat2.shape[-1]
if input is not None and len(input.shape) == 1:
input = input.view(1, -1)
if out is None:
out = input.new_empty([m, n])
if input is None:
input = out
beta = 0
ops.infer.addmm(input, mat1, mat2, beta, alpha, out, None, 0)
return out
def fused_addmm_bias_col_act(
input, mat1, mat2, *, beta=1, alpha=1, out=None, bias=None, activation=2
):
"""
Args:
input: (m,n) torch.float16, torch.bfloat16, torch.float32
mat1: (m,k) torch.float16, torch.bfloat16, torch.float32
mat2: (k,n) torch.float16, torch.bfloat16, torch.float32
beta: float
alpha: float
out: (m,n) torch.float16, torch.bfloat16, torch.float32
当out的shape为(m,n)时,如果out是is_continouns,则bias 必须为(1,n), 否则,bias为(m,1)
bias: (1,n) or (m,1)
activation: str or int
"fused_bias_col": 2, "fused_bias_gelu": 3, "fused_bias_relu": 4
Returns:
out: (m,n) torch.float16, torch.bfloat16, torch.float32
"""
assert mat1.dim() == mat2.dim(), "addmm mat1 mat2 tensors must be 2-D"
assert mat1.size(1) == mat2.size(
0
), f"addmm cannot be multiplied, {mat1.size(0)}X{mat1.size(1)} and {mat2.size(0)}X{mat2.size(1)}"
if isinstance(activation, int):
assert activation in id_to_activation
if isinstance(activation, str):
assert activation in activation_to_id
activation = activation_to_id[activation]
m = mat1.shape[0]
n = mat2.shape[-1]
if out is None:
out = input.new_empty([m, n])
if input is None:
input = out
beta = 0
# activations
if activation == 2:
assert bias is not None
if mat1.dtype == torch.float:
ops.infer.addmm(input, mat1, mat2, beta, alpha, out, None, 0)
out.add_(bias)
return out
elif activation == 3:
assert bias is not None
if mat1.dtype == torch.float:
ops.infer.addmm(input, mat1, mat2, beta, alpha, out, None, 0)
out.add_(bias)
out.copy_(torch.nn.functional.gelu(out))
return out
elif mat1.dtype == torch.bfloat16:
ops.infer.addmm(input, mat1, mat2, beta, alpha, out, bias, 2)
out.copy_(torch.nn.functional.gelu(out))
return out
elif activation == 4:
assert bias is not None
if mat1.dtype == torch.float:
ops.infer.addmm(input, mat1, mat2, beta, alpha, out, None, 0)
out.add_(bias)
out.copy_(torch.nn.functional.relu(out))
return out
elif mat1.dtype == torch.bfloat16:
ops.infer.addmm(input, mat1, mat2, beta, alpha, out, bias, 2)
out.copy_(torch.nn.functional.relu(out))
return out
ops.infer.addmm(input, mat1, mat2, beta, alpha, out, bias, activation)
return out
def ref_bmm(
input: torch.Tensor,
mat2: torch.Tensor,
alpha: float = 1,
format: str = "NN",
input_scales: torch.Tensor = None,
mat2_scales: torch.Tensor = None,
out_dtype: torch.dtype = None,
out: torch.Tensor = None,
):
if format[1] == "T":
input = input.transpose(-1, -2)
if format[0] == "T":
mat2 = mat2.transpose(-1, -2)
m = input.size(-2)
n = mat2.size(-1)
bs = input.size(0)
if input.dtype != torch.int8:
out_dtype = input.dtype
if out is None:
out = torch.empty([bs, m, n], dtype=out_dtype, device=input.device)
if input.dtype != torch.int8:
torch.bmm(input, mat2, out=out)
if alpha != 1:
out = out * alpha
else:
input = input.float() * input_scales.view(1, -1, 1)
mat2 = mat2.float() * mat2_scales.view(1, 1, -1)
out = torch.bmm(input.float(), mat2.float()) * alpha
out = out.to(out_dtype)
return out
def bmm(
input: torch.Tensor,
mat2: torch.Tensor,
alpha: float = 1,
format: str = "NN",
input_scales: torch.Tensor = None,
mat2_scales: torch.Tensor = None,
out_dtype: torch.dtype = None,
out: torch.Tensor = None,
):
"""
out = (input@mat2)*alpha
Support three formats:
format: "NN" input shape: (b, m, k) mat2 shape: (b, k, n) out shape: (b, m, n).
If the dtype of input is int8, the following conditions need to be met: n%64==0 k%64==0
format: "TN" input shape: (b, m, k) mat2 shape: (b, n, k) out shape: (b, m, n)
If the dtype of input is int8, the following conditions need to be met: n%2==0 k%64==0
format: "NT" input shape: (b, k, m) mat2 shape: (b, k, n) out shape: (b, m, n)
If the dtype of input is int8, the following conditions need to be met: m%64==0 n%64==0 k%64==0
If the dtype of input is int8, it is necessary to specify out_dtype.
Args:
input: (b, m, k) or (b, k, m) torch.float16, torch.bfloat16, int8
mat2: (b, k, n) or (b, n, k) torch.float16, torch.bfloat16, int8
alpha: float32
format: TN,NN,NT string
input_scales: (m) torch.float32
mat2_scales: (n) torch.float32
out_dtype: torch.float16, torch.bfloat16
out: (b, m, n) torch.float16, torch.bfloat16
Returns:
out: (b, m, n) torch.float16, torch.bfloat16
"""
if format[1] == "N":
m = input.size(-2)
k = input.size(-1)
else:
m = input.size(-1)
k = input.size(-2)
if format[0] == "N":
n = mat2.size(-1)
else:
n = mat2.size(-2)
if input.dtype == torch.int8:
if format == "TN":
assert (
n % 2 == 0 and k % 64 == 0
), f"bmm shape error, m={m} n={n} k={k}."
elif format == "NT":
assert (
m % 64 == 0 and n % 64 == 0 and k % 64 == 0
), f"bmm shape error, m={m} n={n} k={k}."
elif format == "NN":
assert (
n % 64 == 0 and k % 64 == 0
), f"bmm shape error, m={m} n={n} k={k}."
bs = input.size(0)
if out is None:
if input.dtype != torch.int8:
out_dtype = input.dtype
else:
assert out_dtype is not None
out = torch.empty([bs, m, n], dtype=out_dtype, device=input.device)
ops.infer.bmm(input, mat2, input_scales, mat2_scales, alpha, format, out)
return out