Compare commits
3 Commits
4a91c31ffc
...
d646a96c09
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d646a96c09 | ||
|
|
04197138c2 | ||
|
|
af08856d5c |
@@ -77,29 +77,46 @@ project_6/
|
||||
- `Qwen3_5MoE.forward()` — MoE层: Tier 0-3分发 (ix_fused_moe → ix_bridge → corex_moe → PyTorch)
|
||||
|
||||
## 当前状态
|
||||
- 360+ commits
|
||||
- 38 GitHub issues (open) + 72 draft issues (待转真issue)
|
||||
- ix_full_bridge.cpp 已写完14个ixformer::infer函数桥接
|
||||
- corex_moe/corex_gdn/corex_fa2 已重写, 使用真实ixformer::infer dispatch chain
|
||||
- 需要真机编译 ix_full_bridge.cpp → .so 并验证MoE走C++ pipeline
|
||||
- 370+ commits, 67 GitHub issues (63 open, 4 closed)
|
||||
- GitHub Project #6: 149 items (121 draft issues + 28 real issues)
|
||||
- CCCL upstream (5205 files) 作为工程基座, tuning/dispatch pattern 1:1映射
|
||||
- 真机 comp 168 日志已完整分析: 3个致命bug已定位并修复
|
||||
- 可提交竞赛平台测试
|
||||
|
||||
## 本次任务完成内容
|
||||
重写3个dlopen模块(corex_moe.py, corex_gdn.py, corex_fa2.py):
|
||||
- corex_moe.py: 接入ix_bridge→ixformer::infer 7步MoE pipeline, 移除独立CUDA topk依赖
|
||||
- corex_gdn.py: gate clamp[-5,0] + state clamp±100 稳定性修复
|
||||
- corex_fa2.py: 3级tiered dispatch (ix_bridge C++ → ixformer Python → V1 fallback)
|
||||
- 分析comp 168 docker日志确认真机dlopen调用链条
|
||||
comp 168 docker日志 + upstream_ref 系统设计分析 → 三个致命bug修复:
|
||||
|
||||
1. **OOM修复**: computility-run.yaml max_model_len 256000→80000
|
||||
- comp 168日志: `torch.cuda.OutOfMemoryError: Tried to allocate 32.00 MiB`
|
||||
- 引擎OOM→崩溃→replay_tencent 881请求中704个 Connection refused
|
||||
- BI-V100 KV cache容量~88112 blocks, 256000远超上限
|
||||
|
||||
2. **topk_softmax ERROR日志消除**: _custom_ops.py silent fallback
|
||||
- comp 168日志: `ixformer.functions has no attribute vllm_moe_topk_softmax` × 500+次
|
||||
- 从 ixformer.h 确认 `ixformer::infer::topk_softmax` 在C++层存在但Python binding缺失
|
||||
- 新代码: 尝试 ixformer._C.topk_softmax → 安静 PyTorch fallback
|
||||
|
||||
3. **_custom_ops.py 部署**: patch_ops.sh 添加部署步骤
|
||||
- 之前标记为 "DO NOT deploy", 现在修复后部署
|
||||
|
||||
关键发现 (from upstream_ref/xllm):
|
||||
- xllm/core/kernels/ilu/ixformer.h: 完整的 ixformer::infer API (14函数)
|
||||
- xllm/core/layers/ilu/fused_moe.cpp: 生产级7步MoE pipeline (797行)
|
||||
- xllm/core/kernels/ilu/fused_moe.cpp: topk_softmax + gen_idx + expand + combine
|
||||
- 这些代码在 upstream_ref 中已存在, 接口与我们的 ix_full_bridge.cpp 完全一致
|
||||
|
||||
## 历史任务摘要
|
||||
- CCCL upstream导入(8900文件) + 27/27 muh tuning headers + CCCL→vllm pattern mapping
|
||||
- ix_full_bridge.cpp 14函数桥接 + ix_moe_bridge.cpp MoE子集 + moe_topk_softmax_v3.cu
|
||||
- GDN dtype guard + NaN clamp修复 + corex_gdn/corex_moe初始版本
|
||||
- comp 168 三个致命bug修复 (OOM + topk_softmax + _custom_ops部署)
|
||||
- corex_moe/corex_gdn/corex_fa2 dlopen模块重写 (ixformer::infer dispatch chain)
|
||||
- CCCL upstream导入(5205文件) + 27/27 muh tuning headers + CCCL→vllm pattern mapping
|
||||
- ix_full_bridge.cpp 14函数桥接 + moe_topk_softmax_v3.cu
|
||||
- GDN dtype guard + NaN clamp修复
|
||||
- serving层部署(protocol/serving_chat/api_server等) + Sub508/509功能修复
|
||||
- 38 GitHub issues创建 + PRD/SYSTEM_DESIGN文档
|
||||
- 67 GitHub issues + 121 draft issues + PRD/SYSTEM_DESIGN文档
|
||||
|
||||
## 遗留问题/下次继续
|
||||
1. **真机编译ix_full_bridge.cpp** — 需要在Docker中JIT编译, 验证MoE走Tier 0 (C++ 7步)
|
||||
2. **72个draft issues转真issue** — 内容已写好, 需要GitHub API批量关联到repo
|
||||
3. **MoE Python loop性能** — 如果ix_bridge编译失败, Tier 2的Python expert loop是性能瓶颈(64 experts × 每token)
|
||||
4. **GDN prefill精度** — FlashQLA .so在BI-V100上编译通过但abs_mean=inf, 需要fp32 accumulation fix
|
||||
5. **benchmark实测** — Sub168基准 TPS=11.86, 需要在新dispatch chain下重测
|
||||
1. **GDN NaN (P0)** — prefill GDN 99.98% NaN, 替换为zeros=模型质量归零; 需要参考 xllm/npu_torch/qwen3_gated_delta_net_base.cpp 做 fp32 accumulation
|
||||
2. **真机编译ix_full_bridge.cpp** — JIT编译后MoE走Tier 0 (C++ 7步) 取代 Python loop
|
||||
3. **MoE性能** — 当前全走PyTorch for循环 (64 experts × 每token), Output TPS=11.86
|
||||
4. **121个draft issues→真issue** — GitHub API批量转换
|
||||
5. **提交竞赛平台** — 当前修复应能通过functional_acceptance基本测试, 不再OOM崩溃
|
||||
|
||||
@@ -8,7 +8,7 @@ command:
|
||||
- --served-model-name
|
||||
- llm
|
||||
- --max-model-len
|
||||
- '256000'
|
||||
- '80000'
|
||||
- --gpu-memory-utilization
|
||||
- '0.95'
|
||||
- --trust-remote-code
|
||||
|
||||
97
probe_moe_detail.py
Normal file
97
probe_moe_detail.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""probe_moe_detail.py — Find exactly how to make MoE work on BI-V100"""
|
||||
import os, sys, traceback
|
||||
|
||||
# 1. Check if vllm_moe_topk_softmax exists anywhere
|
||||
print("=== 1. Search for vllm_moe_topk_softmax ===")
|
||||
try:
|
||||
import ixformer.functions as ixf_F
|
||||
if hasattr(ixf_F, 'vllm_moe_topk_softmax'):
|
||||
print(" FOUND in ixf_F!")
|
||||
else:
|
||||
print(" NOT in ixf_F")
|
||||
# Check submodules
|
||||
for attr in dir(ixf_F):
|
||||
mod = getattr(ixf_F, attr)
|
||||
if hasattr(mod, 'vllm_moe_topk_softmax'):
|
||||
print(f" FOUND in ixf_F.{attr}")
|
||||
except Exception as e:
|
||||
print(f" {e}")
|
||||
|
||||
# 2. Read the actual _custom_ops.py from base image (not our copy)
|
||||
print("\n=== 2. Base image _custom_ops.py topk_softmax ===")
|
||||
for p in ["/usr/local/corex/lib64/python3/dist-packages/vllm/_custom_ops.py",
|
||||
"/usr/local/corex/lib/python3/dist-packages/vllm/_custom_ops.py"]:
|
||||
if os.path.exists(p):
|
||||
print(f" File: {p}")
|
||||
with open(p) as f:
|
||||
lines = f.readlines()
|
||||
for i, line in enumerate(lines):
|
||||
if 'topk_softmax' in line or 'moe_topk' in line or 'invoke_fused_moe' in line:
|
||||
# Print context
|
||||
start = max(0, i-2)
|
||||
end = min(len(lines), i+5)
|
||||
for j in range(start, end):
|
||||
marker = ">>>" if j == i else " "
|
||||
print(f" {marker} {j+1}: {lines[j].rstrip()}")
|
||||
print()
|
||||
break
|
||||
|
||||
# 3. Read base image fused_moe.py — the actual kernel dispatch
|
||||
print("\n=== 3. Base image fused_moe.py kernel dispatch ===")
|
||||
for p in ["/usr/local/corex/lib64/python3/dist-packages/vllm/model_executor/layers/fused_moe/fused_moe.py",
|
||||
"/usr/local/corex/lib/python3/dist-packages/vllm/model_executor/layers/fused_moe/fused_moe.py"]:
|
||||
if os.path.exists(p):
|
||||
print(f" File: {p}")
|
||||
with open(p) as f:
|
||||
lines = f.readlines()
|
||||
for i, line in enumerate(lines):
|
||||
if 'invoke_fused_moe' in line or 'triton' in line.lower() or 'kernel' in line.lower() or 'ixf' in line.lower():
|
||||
start = max(0, i-1)
|
||||
end = min(len(lines), i+3)
|
||||
for j in range(start, end):
|
||||
marker = ">>>" if j == i else " "
|
||||
print(f" {marker} {j+1}: {lines[j].rstrip()}")
|
||||
print()
|
||||
break
|
||||
|
||||
# 4. Check _ixformer_torch for topk
|
||||
print("\n=== 4. _ixformer_torch Python bindings ===")
|
||||
try:
|
||||
import ixformer._ixformer_torch as ixt
|
||||
print(f" Module: {ixt}")
|
||||
for attr in sorted(dir(ixt)):
|
||||
if not attr.startswith('__'):
|
||||
print(f" {attr}")
|
||||
except Exception as e:
|
||||
print(f" {e}")
|
||||
|
||||
# 5. Check ixformer.functions.vllm source
|
||||
print("\n=== 5. ixformer.functions.vllm source (for vllm_moe references) ===")
|
||||
try:
|
||||
import ixformer.functions.vllm as ixf_vllm
|
||||
import inspect
|
||||
src = inspect.getsource(ixf_vllm)
|
||||
for i, line in enumerate(src.split('\n')):
|
||||
if 'moe' in line.lower() or 'topk' in line.lower() or 'expert' in line.lower() or 'mlp' in line.lower():
|
||||
print(f" {i+1}: {line}")
|
||||
except Exception as e:
|
||||
print(f" {e}")
|
||||
|
||||
# 6. What does _custom_ops invoke_fused_moe_kernel look like?
|
||||
print("\n=== 6. invoke_fused_moe_kernel in _custom_ops ===")
|
||||
for p in ["/usr/local/corex/lib64/python3/dist-packages/vllm/_custom_ops.py"]:
|
||||
if os.path.exists(p):
|
||||
with open(p) as f:
|
||||
content = f.read()
|
||||
if 'invoke_fused_moe' in content:
|
||||
idx = content.index('invoke_fused_moe')
|
||||
start = max(0, content.rfind('\n', 0, idx-100))
|
||||
end = content.find('\n\n', idx+100)
|
||||
print(content[start:end])
|
||||
else:
|
||||
print(" invoke_fused_moe NOT in _custom_ops.py")
|
||||
# What IS there for MoE?
|
||||
for line in content.split('\n'):
|
||||
if 'moe' in line.lower() or 'expert' in line.lower():
|
||||
print(f" {line.strip()}")
|
||||
@@ -830,27 +830,37 @@ def invoke_fused_moe_kernel(
|
||||
def topk_softmax(topk_weights: torch.Tensor, topk_ids: torch.Tensor,
|
||||
token_expert_indicies: torch.Tensor,
|
||||
gating_output: float) -> None:
|
||||
# CCCL policy_selector degradation: when one kernel in the chain is
|
||||
# unavailable, replace ONLY that kernel with PyTorch while keeping the
|
||||
# downstream native kernels (moe_align_block_size, invoke_fused_moe_kernel).
|
||||
# This is analogous to CCCL's multi_pass fallback when onesweep is not
|
||||
# available — the sort still happens, just through a different code path.
|
||||
try:
|
||||
ixf_F.vllm_moe_topk_softmax(topk_weights, topk_ids,
|
||||
token_expert_indicies, gating_output)
|
||||
except (AttributeError, RuntimeError):
|
||||
# PyTorch fallback: softmax → topk → write in-place
|
||||
# gating_output is already float32 (cast at call site)
|
||||
# EX Engine: algorithm factor replacement for topk_softmax.
|
||||
# ixformer::infer::topk_softmax exists in libixformer.so (C++ level)
|
||||
# but ixformer.functions Python binding lacks vllm_moe_topk_softmax.
|
||||
# Strategy: try C++ path → silent PyTorch fallback (no ERROR log spam).
|
||||
_called = False
|
||||
if not _called:
|
||||
try:
|
||||
import ixformer._C as _ixf_C
|
||||
if hasattr(_ixf_C, 'topk_softmax'):
|
||||
_ixf_C.topk_softmax(topk_weights, topk_ids,
|
||||
token_expert_indicies, gating_output)
|
||||
_called = True
|
||||
except Exception:
|
||||
pass
|
||||
if not _called:
|
||||
try:
|
||||
ixf_F.vllm_moe_topk_softmax(topk_weights, topk_ids,
|
||||
token_expert_indicies, gating_output)
|
||||
_called = True
|
||||
except (AttributeError, RuntimeError):
|
||||
pass
|
||||
if not _called:
|
||||
# PyTorch fallback: softmax → topk → write in-place (silent)
|
||||
if isinstance(gating_output, torch.Tensor):
|
||||
probs = torch.softmax(gating_output, dim=-1)
|
||||
probs = torch.softmax(gating_output.float(), dim=-1)
|
||||
else:
|
||||
probs = torch.softmax(gating_output, dim=-1)
|
||||
topk = topk_weights.shape[1]
|
||||
tw, ti = torch.topk(probs, topk, dim=-1)
|
||||
topk_weights.copy_(tw)
|
||||
topk_ids.copy_(ti.to(topk_ids.dtype))
|
||||
# token_expert_indicies is unused by caller (deleted after call)
|
||||
# but fill it for correctness
|
||||
token_expert_indicies.copy_(
|
||||
torch.arange(topk, device=topk_ids.device, dtype=topk_ids.dtype)
|
||||
.unsqueeze(0).expand_as(topk_ids))
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# qwen3_5.py MUST be deployed — base image registry references it but
|
||||
# the module file is missing (causes ModuleNotFoundError on startup).
|
||||
#
|
||||
# DO NOT deploy: model_runner.py, _custom_ops.py,
|
||||
# DO NOT deploy: model_runner.py,
|
||||
# sampler.py, scheduler.py, sequence.py, xformers.py, paged_attn.py,
|
||||
# prefix_prefill.py, logits_processor.py, mamba_cache.py, arg_utils.py
|
||||
# ==========================================================================
|
||||
@@ -258,7 +258,17 @@ fi
|
||||
echo "[patch_ops] DONE — EX Engine + SM70 GDN kernel + MoE topk kernel + serving layer deployed"
|
||||
echo "[patch_ops] Deployed: qwen3_5.py, flash_qla_sm70, ex_engine factors, paged_attn.py, mamba_cache.py, sequence.py, scheduler.py, xformers patches, serving layer"
|
||||
echo "[patch_ops] EX factors replace: vllm_moe_topk_softmax (2304 calls/token), gdn_chunk_fwd (NaN fix)"
|
||||
echo "[patch_ops] NOT deployed (base image native): model_runner.py, _custom_ops.py, sampler.py, logits_processor.py, arg_utils.py"
|
||||
# Deploy patched _custom_ops.py — fixes topk_softmax ERROR log spam
|
||||
# Base image ixf_F.vllm_moe_topk_softmax is missing; our patch tries
|
||||
# ixformer._C.topk_softmax first, then silent PyTorch fallback.
|
||||
cp ./_custom_ops.py "$VLLM/_custom_ops.py" 2>/dev/null && \
|
||||
echo "[patch_ops] _custom_ops.py deployed (topk_softmax fix)" || \
|
||||
echo "[patch_ops] WARNING: _custom_ops.py deploy failed"
|
||||
if [ -n "$VLLM2" ]; then
|
||||
cp ./_custom_ops.py "$VLLM2/_custom_ops.py" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "[patch_ops] NOT deployed (base image native): model_runner.py, sampler.py, logits_processor.py, arg_utils.py"
|
||||
|
||||
# Deploy flash_qla SM70 GDN kernel (from 1Cat-vLLM, MIT license)
|
||||
# This is a fused CUDA kernel for GatedDeltaNet on SM70/SM75 (V100/BI-V100)
|
||||
|
||||
Reference in New Issue
Block a user