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

200 lines
6.3 KiB
Python

import ixformer._C as ops
import torch
__all__ = [
"ref_bert_embedding",
"bert_embedding",
"ref_bert_add_norm",
"bert_add_norm",
"ref_bert_unpack_start_end_logits",
"bert_unpack_start_end_logits",
"ref_bert_linear_residual",
"bert_linear_residual",
]
def ref_bert_embedding(
token_weight: torch.Tensor,
pos_weight: torch.Tensor,
type_weight: torch.Tensor,
ln_weight: torch.Tensor,
ln_bias: torch.Tensor,
token_ids: torch.Tensor,
pos_ids: torch.Tensor,
type_ids: torch.Tensor,
epsilon: float = 1e-5,
out: torch.Tensor = None,
):
assert out is None
emd1 = torch.nn.functional.embedding(token_ids, token_weight)
emd2 = torch.nn.functional.embedding(pos_ids, pos_weight)
emd3 = torch.nn.functional.embedding(type_ids, type_weight)
out = emd1 + emd2 + emd3
out = torch.nn.functional.layer_norm(out, [out.shape[-1]], ln_weight, ln_bias)
return out
def bert_embedding(
token_weight: torch.Tensor,
pos_weight: torch.Tensor,
type_weight: torch.Tensor,
ln_weight: torch.Tensor,
ln_bias: torch.Tensor,
token_ids: torch.Tensor,
pos_ids: torch.Tensor,
type_ids: torch.Tensor,
epsilon: float = 1e-5,
out: torch.Tensor = None,
):
"""
Args:
token_weight: (vocab_size, hidden_size) torch.float16, torch.bfloat16
pos_weight: (pos_size, hidden_size) same as token_weight
type_weight: (type_size, hidden_size) same as token_weight
ln_weight: (hidden_size) same as token_weight
ln_bias: (hidden_size) same as token_weight
token_ids: (num_tokens) torch.int32, torch.int64
pos_ids: (num_tokens) same as token_ids
type_ids: (num_tokens) same as token_ids
epsilon: float
out: (num_tokens, hidden_size) same as token_weight
Returns:
out: (num_tokens, hidden_size) same as token_weight
"""
if out is None:
out_shape = list(token_ids.shape)
hidden_size = token_weight.shape[-1]
out_shape.append(hidden_size)
out = token_weight.new_empty(out_shape)
ops.infer.bert_embedding(
token_weight,
pos_weight,
type_weight,
ln_weight,
ln_bias,
token_ids,
pos_ids,
type_ids,
out,
epsilon,
)
return out
def ref_bert_add_norm(
input: torch.Tensor,
residual: torch.Tensor,
ln_weight: torch.Tensor,
ln_bias: torch.Tensor,
epsilon: float = 1e-5,
out: torch.Tensor = None,
):
assert out is None
input = input + residual
return torch.nn.functional.layer_norm(
input, [input.shape[-1]], ln_weight, ln_bias, epsilon
)
def bert_add_norm(
input: torch.Tensor,
residual: torch.Tensor,
ln_weight: torch.Tensor,
ln_bias: torch.Tensor,
epsilon: float = 1e-5,
out: torch.Tensor = None,
):
"""
out = input + residual
out = add_norm(out, ln_weight, ln_bias, epsilon)
Args:
input: (num_tokens, hidden_size) torch.float16, torch.bfloat16
residual: (num_tokens, hidden_size) same as input
ln_weight: (hidden_size) same as input
ln_bias: (hidden_size) same as input
epsilon: float
out: (num_tokens, hidden_size) same as input
Returns:
out: (num_tokens, hidden_size) same as input
"""
if out is None:
out = torch.empty_like(input)
ops.infer.bert_add_norm(input, residual, ln_weight, ln_bias, out, epsilon)
return out
def ref_bert_unpack_start_end_logits(
logits: torch.Tensor,
cu_seq_lens: torch.Tensor,
max_seq_len: int,
start_logits: torch.Tensor = None,
end_logits: torch.Tensor = None,
):
batch_size = cu_seq_lens.shape[0] - 1
if start_logits is None:
start_logits = logits.new_empty([batch_size, max_seq_len])
if end_logits is None:
end_logits = logits.new_empty([batch_size, max_seq_len])
cu_seq_len_cpu = cu_seq_lens.detach().cpu()
for i in range(batch_size):
start_idx = cu_seq_len_cpu[i]
end_idx = cu_seq_len_cpu[i + 1]
cur_len = end_idx - start_idx
start_logits[i, :cur_len] = logits[start_idx:end_idx, 0]
end_logits[i, :cur_len] = logits[start_idx:end_idx, 1]
return start_logits, end_logits
def bert_unpack_start_end_logits(
logits: torch.Tensor,
cu_seq_lens: torch.Tensor,
max_seq_len: int,
start_logits: torch.Tensor = None,
end_logits: torch.Tensor = None,
):
"""
Args:
logits: (num_tokens, 2) torch.float16, torch.bfloat16
cu_seq_lens: (batch_size+1) torch.int32, torch.int64
max_seq_len: int
start_logits: (batch_size, max_seq_len) same as logits
end_logits: (batch_size, max_seq_len) same as logits
Returns:
start_logits: (batch_size, max_seq_len) same as logits
end_logits: (batch_size, max_seq_len) same as logits
"""
batch_size = cu_seq_lens.shape[0] - 1
if start_logits is None:
start_logits = logits.new_empty([batch_size, max_seq_len])
if end_logits is None:
end_logits = logits.new_empty([batch_size, max_seq_len])
ops.infer.bert_unpack_start_end_logits(
logits, cu_seq_lens, start_logits, end_logits
)
return start_logits, end_logits
def ref_bert_linear_residual(
input: torch.Tensor, weight: torch.Tensor, bias: torch.Tensor, out: torch.Tensor
):
return torch.nn.functional.linear(input, weight, bias) + out
def bert_linear_residual(
input: torch.Tensor, weight: torch.Tensor, bias: torch.Tensor, out: torch.Tensor
):
"""
Args:
input: (m, k) torch.float16, torch.bfloat16
weight: (n, k) same as input
bias: (n) same as input
out: (m, n) same as input
Returns:
out: (m, n) same as input
"""
ops.infer.bert_linear_residual(input, weight, bias, out)
return out