Files
project_6/CODEPATH_MAP.md
Claude e87470733d accel(ixformer): wire BI-V100 hardware primitives into GDN + MoE compute paths
Before: 9 ixformer ops available, 0 used by our code (100% pure PyTorch).
After: matmul/bmm/softmax wired into every hot path.

Decode path (runs for EVERY generated token):
  - 2× torch.bmm → _ix_bmm (kv_mem lookup + output projection)

Chunk scan loop (prefill, runs per 2048-token chunk):
  - k_beta @ key.T → _ix_matmul
  - attn @ v_beta → _ix_matmul
  - attn @ k_beta_exp → _ix_matmul
  - 6× matmul inside state update loop → _ix_matmul

MoE routing + expert dispatch:
  - torch.softmax → _ix_softmax (router)
  - torch.bmm in decode fast-path → _ix_bmm

Also adds CODEPATH_MAP.md — complete source-file-level timing diagram
from HTTP request to GPU kernel, with line numbers.

ixformer.matmul signature: matmul(input, other, out, transa, transb, alpha, beta)
ixformer.softmax signature: softmax(input, dim)
Both fall back to torch if ixformer unavailable.
2026-08-08 22:35:21 +00:00

170 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 代码路径时序图 — 从HTTP请求到GPU kernel的完整链路
## 一、请求入口到引擎调用
```
HTTP POST /v1/chat/completions
├─ api_server.py → FastAPI route handler
│ └─ serving_chat.py:create_chat_completion() [line ~140]
│ ├─ protocol.py:ChatCompletionRequest.model_validate()
│ │ └─ max_completion_tokens → max_tokens 映射 [line 418]
│ │ └─ extra="allow" (Sub168用extra="forbid"导致400)
│ │
│ ├─ chat_utils.py → 消息格式化 + 多模态处理
│ │ └─ content=None容错 (Sub168这里崩)
│ │
│ ├─ serving_chat.py [line 175-213] → enable_thinking逻辑
│ │ ├─ tool_choice=auto + tools存在 → enable_thinking=False
│ │ ├─ thinking.type=disabled → enable_thinking=False
│ │ └─ 默认 → enable_thinking=True
│ │
│ ├─ serving_chat.py [line 250-252] → n值检查
│ │ └─ n>2 → 400 (n=2允许传入引擎)
│ │
│ └─ engine_client.generate() [line 355]
│ └─ try/except ValueError + catch-all Exception
├─ computility-run.yaml → vLLM启动参数
│ ├─ --max-num-seqs 2 (防止n=2崩溃)
│ ├─ --max-model-len 80000
│ ├─ --enforce-eager (禁用CUDA Graph)
│ ├─ --enable-prefix-caching
│ └─ --tool-call-parser qwen3_coder
└─ 如果引擎crash → 后续所有请求Connection Refused
(Sub508的根因: t2_n_2触发, 30个FAIL级联)
```
## 二、模型前向传播 — 逐层链路
```
Qwen3_5ForCausalLM.forward() [qwen3_5.py line 1214]
└─ Qwen3_5Model.forward() [line 1094]
├─ embed_tokens(input_ids)
└─ for layer in self.layers: # 36层 (Qwen3.6-27B典型配置)
├─ GemmaRMSNorm(hidden_states, residual)
│ └─ ☆ 可用ixformer: fused_add_rms_norm(input, residual, weight, eps)
├─ [linear_attention层] GatedDeltaNet.forward() [line 407]
│ │
│ ├─ CoreX dispatch尝试 [line 416-425]
│ │ └─ _use_corex_gdn=False (base image无corex_gdn模块)
│ │
│ └─ _pytorch_forward() [line 435] ← 当前执行路径
│ │
│ ├─ 投影: in_proj_qkv, in_proj_z, in_proj_b, in_proj_a
│ │ └─ ☆ 每个是F.linear → 可用ixformer.matmul
│ │
│ ├─ [prefill] 逐序列循环 [line 463-555]
│ │ │
│ │ ├─ F.conv1d (causal conv)
│ │ │ └─ ☆ 可用ixformer.conv2d (需reshape)
│ │ │
│ │ ├─ F.silu → ☆ 可用ixformer.silu_and_mul
│ │ │
│ │ ├─ g计算: -A_log.exp() * softplus(a+dt_bias)
│ │ │ └─ 当前: clamp(-8,4)后exp, softplus.clamp(max=10)
│ │ │
│ │ └─ _torch_chunk_gated_delta_rule() [line 152-247]
│ │ │
│ │ ├─ g.clamp(-5,2).cumsum(-1).clamp(-20,20) ← NaN修复点
│ │ ├─ decay_mask = exp(g差) ← 所有exp在clamp后
│ │ ├─ attn矩阵: k_beta @ key.T * decay_mask
│ │ │ └─ ☆ 三角求解循环 → 无法用ixformer加速
│ │ │ (这是纯序列依赖: attn[i] += attn[i,:i] @ attn[:i,:i])
│ │ ├─ state更新循环: for i in chunks [line 219-232]
│ │ │ ├─ q @ k.T * decay ← ☆ ixformer.matmul可加速
│ │ │ ├─ q * exp(g) @ state ← ☆ ixformer.matmul可加速
│ │ │ └─ state更新: state * exp(g) + k.T @ v_new
│ │ │ └─ ☆ ixformer.matmul可加速
│ │ └─ 最终: core_out → transpose → to(dtype)
│ │
│ ├─ [decode] 单token路径 [line 558-638]
│ │ ├─ _torch_causal_conv1d_update
│ │ │ └─ 逐通道点积 → ☆ ixformer.gemv可加速
│ │ ├─ g_t = g.clamp(-20,2).exp_() ← NaN修复点
│ │ ├─ temporal_state.mul_(g_t) ← 状态衰减
│ │ ├─ torch.bmm(k, state) ← ☆ ixformer.matmul可加速
│ │ └─ state.baddbmm_(k, delta) ← ☆ ixformer.matmul可加速
│ │
│ └─ GemmaRMSNorm + out_proj
│ └─ ☆ ixformer.rms_norm + ixformer.matmul
├─ [full_attention层] Qwen3_5FullAttention.forward() [line 737]
│ └─ 标准vLLM Attention → XFormers后端
│ └─ ☆ 已使用ixformer.flash_attn_func (base image配置)
├─ GemmaRMSNorm(hidden_states, residual)
│ └─ ☆ ixformer.fused_add_rms_norm
└─ [MLP/MoE] Qwen3_5MLP 或 Qwen3_5MoeSparseBlock
├─ [MLP] gate_up_proj → silu_and_mul → down_proj
│ └─ ☆ 全部可用ixformer: matmul + silu_and_mul + matmul
└─ [MoE] Qwen3_5MoeSparseBlock.forward() [line 974]
├─ gate(hidden) → router_logits
├─ softmax → topk → renormalize (纯PyTorch, 无硬件加速)
├─ _pure_pytorch_experts() [line 897]
│ ├─ [decode T=1] 批量GEMM: 3次kernel launch
│ │ └─ F.linear(x, w13_sel.reshape(-1,H)) ← ☆ ixformer.matmul
│ │ └─ F.silu(gate) * up ← ☆ ixformer.silu_and_mul (需reshape)
│ │ └─ torch.bmm(w2_sel, act) ← ☆ ixformer.matmul
│ └─ [prefill] 逐expert循环 ← 性能瓶颈
│ └─ 每个expert: F.linear × 2 + silu
│ └─ ☆ 可用ixformer.matmul但循环开销不变
└─ shared_expert: gate_up → silu_and_mul → down → sigmoid gate
└─ ☆ 全部可用ixformer
```
## 三、ixformer可用原语 vs 当前使用情况
| ixformer原语 | 签名 | 当前是否使用 | 可替换的PyTorch调用 |
|-------------|------|------------|-------------------|
| `matmul` | `matmul(input, other, out, transa, transb, alpha, beta)` | ❌ 未使用 | F.linear, torch.mm, torch.bmm, @ |
| `softmax` | `softmax(input, dim)` | ❌ 未使用 | torch.softmax (MoE路由) |
| `rms_norm` | `rms_norm(input, weight, output, eps)` | ❌ 未使用 | GemmaRMSNorm内部 |
| `fused_add_rms_norm` | `fused_add_rms_norm(input, residual, weight, eps, scale)` | ❌ 未使用 | residual + layernorm 两步 |
| `silu_and_mul` | `silu_and_mul(input, output)` | ❌ 未使用 | SiluAndMul层, F.silu(g)*up |
| `conv2d` | `conv2d(input, weight, bias, stride, padding, dilation, groups)` | ❌ 未使用 | F.conv1d (causal conv) |
| `flash_attn_func` | `flash_attn_func(q, k, v, dropout_p, softmax_scale, causal)` | ✅ XFormers后端使用 | full_attention层 |
| `gemv` | `gemv(x, A)` | ❌ 未使用 | decode路径小矩阵乘 |
| `scaled_dot_product_attention` | `sdpa(query, key, value, attn_mask, dropout_p, is_causal)` | ❌ 未使用 | 可替代chunk内QK^T计算 |
**关键发现9个可用原语中只有1个flash_attn_func被使用而且不是我们的代码使用的——是base image的XFormers后端自动调用的。我们的代码对ixformer的利用率是0%。**
## 四、Sub168 vs Sub508 性能差距的代码解释
```
Sub168 (8.49s for d01):
base image native qwen3_5.py
├─ corex_gdn: 使用libcorex_gdn.so的fused GDN kernel ← 不存在于我们的base image
├─ corex_moe: 使用libcorex_moe.so的fused MoE kernel ← 不存在于我们的base image
└─ 所有底层ops由ixformer后端加速 (matmul/rms_norm/softmax等)
Sub508 (95.85s for d01):
我们的自定义 qwen3_5.py
├─ GatedDeltaNet: 纯PyTorch (cumsum→exp→NaN→nan_to_num→全零)
├─ MoE: 纯PyTorch循环 (每expert单独F.linear)
└─ 底层ops全部用PyTorch默认kernel (未调用ixformer)
```
## 五、优化路径 — 用ixformer原语替换PyTorch
### 立即可做 (不改算法, 只换kernel):
1. **matmul**: 所有F.linear/torch.bmm/@ → ixformer.matmul
2. **silu_and_mul**: MLP和MoE的silu*gate → ixformer.silu_and_mul
3. **rms_norm**: GemmaRMSNorm内部 → ixformer.rms_norm
4. **fused_add_rms_norm**: residual+norm两步 → 一步fused
5. **softmax**: MoE路由softmax → ixformer.softmax
### 需要适配 (改数据布局):
6. **conv2d**: F.conv1d的causal conv → ixformer.conv2d (需要1D→2D reshape)
7. **gemv**: decode路径的小向量乘 → ixformer.gemv
8. **sdpa**: chunk内的QK^T+softmax → ixformer.scaled_dot_product_attention