关键发现: - 07-23: base corex chain 完好(GDN+MoE+FA2全fused), 但OOM(max_model_len=100000) - 08-07: 我们覆盖qwen3_5.py打断corex chain → GDN NaN + MoE Python fallback - 修复: patch_ops.sh v2 不覆盖base, max_model_len=80000 - 新增: verify_deployment.sh 真机验证, COMP168_DIAGNOSIS.md
7.9 KiB
comp 168 Docker 诊断 → .so 开发清单
基于
2d5232c5d6bc(comp 168 docker log, 3786 行) 当前 HEAD:b25fc53e(414 commits)
一、comp 168 日志三大致命问题
| # | 错误 | 出现次数 | 根因 | 状态 |
|---|---|---|---|---|
| 1 | GDN NaN frac=0.9998 |
16次(layer 0-4) | 我们的 GDN prefill 实现产生 NaN → replace with zeros → 模型质量归零 | P0 未修 |
| 2 | vllm_moe_topk_softmax not found |
39次 | ixformer.functions 没有 Python binding → fallback to Python for 循环 |
P0 需 .so |
| 3 | CUDA OOM 32 MiB |
17次 | max_model_len=100000 超过 KV cache 容量 → engine 死亡 |
✅ 已修为 80000 |
二、真机探测确认的事实
从你贴的真机 probe 输出:
ixformer.functions 有:
✓ silu_and_mul, rms_norm, fused_add_rms_norm, rotary_embedding
✓ flash_attn_*, vllm_single_query_cached_kv_attention_v2
✓ vllm_cache_ops_reshape_and_cache, vllm_swap_blocks, vllm_copy_cache
✗ vllm_moe_topk_softmax (不存在!)
✗ moe_compute_token_index_api (不存在!)
✗ moe_w16a16_group_gemm (不存在!)
libixformer.so 中:
✓ 上述函数全部存在 (C++ 符号, xllm 的 ixformer.h 声明了它们)
但 Python binding (_C.so) 没有暴露
结论: MoE 7 步 pipeline 中的 topk_softmax / gen_idx / expand / group_gemm / combine 全部需要通过 ix_moe_bridge.so 桥接。
三、需要开发/修复的 .so 清单
SO-1: ix_moe_bridge.so (MoE 7步 pipeline) — ✅ 代码已有,需真机编译验证
源码: ex_engine/csrc/ix_moe_bridge.cpp (258行)
编译: ex_engine/precompile_ix_bridge.py → torch.utils.cpp_extension.load(-lixformer)
状态: 代码写好了,Dockerfile 有 build step,但从未在真机验证过编译成功
真机验证命令:
cd /workspace/ex_engine
python3 precompile_ix_bridge.py
ls -la build/ix_moe_bridge*.so
python3 -c "import torch; from torch.utils.cpp_extension import load; m=load('test', sources=['csrc/ix_moe_bridge.cpp'], extra_ldflags=['-L/usr/local/corex/lib64/python3/dist-packages/ixformer', '-lixformer']); print(dir(m))"
SO-2: GDN prefill 修复 — P0 最高优先级
现状: 我们的 _torch_chunk_gated_delta_rule 在 fp16 下产生 99.98% NaN
参考: upstream_ref/xllm/core/layers/npu_torch/qwen3_gated_delta_net_base.cpp (576行)
关键差异:
- xllm 用
fp32accumulation:decay_mask = ... .exp().float() - xllm 用
torch::matmul而不是自定义 chunk kernel - xllm 的 recurrent state 管理有精确的
clamp(-20, 20)限制
解决方案: 不写新 .so,而是从 xllm 搬运 GDN 的 PyTorch 实现(C++ torch ops, 全 fp32 accumulation),替换我们的 chunk kernel。
SO-3: _custom_ops.py patch — ✅ 已有 fallback 逻辑
base image 的 _custom_ops.py 调用 ixf_F.vllm_moe_topk_softmax 时会报错。
但 comp 168 的 base 镜像绕过了 _custom_ops,直接走 corex_moe.py 的 7 步 pipeline。
如果 base 有 corex_moe.py: 不需要 patch 如果 base 没有 corex_moe.py: 我们的版本 + ix_moe_bridge.so 补位
四、upstream 已有、不需要重写的代码
| upstream 文件 | 行数 | 我们的对应文件 | 搬运状态 |
|---|---|---|---|
xllm/core/kernels/ilu/ixformer.h |
147 | ex_engine/csrc/ilu/ixformer.h |
✅ 已搬 |
xllm/core/kernels/ilu/fused_moe.cpp |
99 | ex_engine/csrc/ilu_kernel_fused_moe.cpp |
✅ 已搬 |
xllm/core/layers/ilu/fused_moe.cpp |
797 | ex_engine/csrc/ilu_layer_fused_moe.cpp |
✅ 已搬 |
xllm/core/kernels/ilu/attention.cpp |
162 | ex_engine/csrc/ilu_kernel_attention.cpp |
✅ 已搬 |
xllm/core/layers/ilu/attention.cpp |
189 | ex_engine/csrc/ilu_layer_attention.cpp |
✅ 已搬 |
xllm/core/kernels/ilu/norm.cpp |
50 | ex_engine/csrc/ilu_kernel_norm.cpp |
✅ 已搬 |
xllm/core/kernels/ilu/activation.cpp |
32 | ex_engine/csrc/ilu_kernel_activation.cpp |
✅ 已搬 |
xllm/core/kernels/ilu/rope.cpp |
31 | ex_engine/csrc/ilu_kernel_rope.cpp |
✅ 已搬 |
xllm/core/kernels/ilu/group_gemm.cpp |
39 | ex_engine/csrc/ilu_kernel_group_gemm.cpp |
✅ 已搬 |
xllm/core/kernels/ilu/matmul.cpp |
73 | ex_engine/csrc/ilu_kernel_matmul.cpp |
✅ 已搬 |
xllm/core/layers/npu_torch/qwen3_gated_delta_net_base.cpp |
576 | ex_engine/csrc/qwen3_gated_delta_net_base.cpp |
✅ 已搬 |
ds_vllm/csrc/moe/topk_softmax_kernels.cu |
874 | ex_engine/csrc/moe_v055/topk_softmax_kernels.cu |
✅ 已搬 |
xllm/core/kernels/cuda/moe/moe_topk_softmax_kernels.cuh |
~400 | ex_engine/csrc/moe/moe_topk_softmax_kernels.cuh |
✅ 已搬 |
五、真机验证 checklist
在真机上按顺序执行:
# 1. 验证 ix_moe_bridge.so 编译
cd /workspace/ex_engine && python3 precompile_ix_bridge.py
ls build/ix_moe_bridge*.so # 必须存在
# 2. 验证符号解析
python3 -c "
import torch
import importlib.util
spec = importlib.util.spec_from_file_location('ix', 'build/ix_moe_bridge.cpython-310-x86_64-linux-gnu.so')
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
print([x for x in dir(m) if not x.startswith('_')])
# 应输出: ['topk_softmax', 'moe_gen_idx', 'moe_expand_input', 'moe_group_gemm',
# 'silu_and_mul', 'moe_combine_result', 'paged_attention', 'rms_norm',
# 'fused_add_rms_norm', 'linear', 'reshape_and_cache', 'rotary_embedding']
"
# 3. 验证 topk_softmax 功能
python3 -c "
import torch
# ... load ix_moe_bridge ...
gating = torch.randn(4, 64, device='cuda', dtype=torch.float32)
tw = torch.empty(4, 8, device='cuda', dtype=torch.float32)
ti = torch.empty(4, 8, device='cuda', dtype=torch.int32)
tei = torch.empty(4, 8, device='cuda', dtype=torch.int32)
m.topk_softmax(tw, ti, tei, gating)
print('topk_weights:', tw)
print('topk_ids:', ti)
"
# 4. 验证 GDN 不再 NaN
# (需要先修复 GDN prefill 代码)
# 5. 启动服务验证
python3 -m vllm.entrypoints.openai.api_server --model /model ...
六、最关键发现:07-23 的 base image 自带完整 corex_* chain
07-23 日志证据 (dockerrizhi.txt):
corex_gdn.py:56 → Loaded fused CoreX GDN decode operator from /usr/local/corex/lib64/libcorex_gdn.so ✅
corex_gdn.py:228 → Using fused CoreX GDN prefill operator ✅
corex_moe.py:339 → Using CoreX fused MoE prefill operator: tokens=4096, kernel=expert-grouped-wmma ✅
corex_fa2.py:333 → Using CoreX FA2 packed prefill: B=2 Hq=4 Hkv=1 D=256 ✅
corex_fa2.py:507 → Using CoreX paged FA2 chunked prefill ✅
08-07 日志: 零条 corex_* 加载记录。取而代之的是 qwen3_5.py:445 NaN in prefill + _custom_ops.py:58 topk_softmax not found。
根因: 08-07 提交部署了我们自己的 qwen3_5.py,覆盖了 base image 自带的版本,打断了 corex_gdn.py / corex_moe.py / corex_fa2.py 的调用链。
当前状态: patch_ops.sh v2 已经有条件跳过逻辑(_QW_SIZE > 1000 → KEEPING IT),但需要确保下次提交时不再触发 qwen3_5.py 覆盖。
结论: 如果 base image 有工作的 corex_* chain,我们只需要:
- 不覆盖 qwen3_5.py
- 只部署 serving 层(protocol/serving_chat/api_server/tool_parser)
max_model_len=80000(已修)ix_moe_bridge.so作为备用(如果 base 的 _custom_ops 有路径碰到 topk_softmax)
七、代码量评估
| 组件 | 文件数 | 总行数 | 状态 |
|---|---|---|---|
| ex_engine/csrc (C++) | 39 | ~8000 | 全部已有,需真机编译 |
| ex_engine/python (Python) | 7 | ~1200 | 全部已有,dispatch chain 完整 |
| qwen3_6_scripts (serving) | 20+ | ~6000 | 全部已有,patch_ops.sh 管部署 |
| upstream_ref (xllm reference) | 500+ | ~100K | 参考用,关键文件已搬到 ex_engine |
结论: 代码量是够的。问题不是代码不够,而是:
- GDN NaN 没修(需要用 xllm 的 fp32 accumulation 逻辑替换)
- ix_moe_bridge.so 从未在真机编译成功
- 没有 "不允许 fallback" 的硬要求落实到代码里