Compare commits
7 Commits
c1065aaf2c
...
a7537ebee0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7537ebee0 | ||
|
|
e87470733d | ||
|
|
5cd2780320 | ||
|
|
68876acd1b | ||
|
|
6b8965a667 | ||
|
|
44003fa829 | ||
|
|
ff971686d4 |
193
CODEPATH_MAP.md
Normal file
193
CODEPATH_MAP.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# 代码路径时序图 — 从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
|
||||
|
||||
## 六、功能测试FAIL根因分析(6个非crash FAIL)
|
||||
|
||||
```
|
||||
FAIL类型A: NaN导致模型输出质量问题 (修NaN后自愈)
|
||||
├─ d03_tool_call: tools=0 — 模型不能输出<tool_call> XML
|
||||
├─ d07_reasoning_plus_content: content[0] — 模型不输出</think>
|
||||
├─ d10_thinking_disable_ctk: 乱码 — 模型logits被NaN扭曲
|
||||
├─ t1a_thinking_true: reasoning[0] — output.text为空→parser返回空
|
||||
└─ t1c_thinking_default: reasoning[0] — 同上
|
||||
|
||||
FAIL类型B: 请求处理层问题
|
||||
└─ d05_multimodal: HTTP 400 — 多模态请求验证失败
|
||||
|
||||
FAIL类型C: 引擎crash级联 (修max-num-seqs=2后自愈)
|
||||
└─ t2_n_2 → t3/t4/t5/t6/t7/t8/t9/t10/t12/t13/t14/t15/t16 全部HTTP 500 (25个)
|
||||
|
||||
当前代码状态:
|
||||
NaN修复: ✅ cumsum前clamp[-5,2] + 后clamp[-20,20] + A_log clamp[-8,4]
|
||||
引擎防崩: ✅ max-num-seqs=2 + catch-all Exception
|
||||
ixformer加速: ✅ matmul/bmm/softmax接入12处热路径
|
||||
reasoning parser: ✅ qwen3已注册,部署正确
|
||||
tool parser: ✅ qwen3_coder已注册,adjust_request禁thinking
|
||||
|
||||
预期: NaN修复后模型质量恢复 → 类型A的5个FAIL自愈
|
||||
max-num-seqs=2 → 类型C的25个FAIL自愈
|
||||
剩余: d05_multimodal需要单独debug
|
||||
预估: 45/51 PASS (88%)
|
||||
```
|
||||
217
HARDWARE_PROBE_20260808.md
Normal file
217
HARDWARE_PROBE_20260808.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# BI-V100 Hardware Probe Results
|
||||
|
||||
Date: 2026-08-08
|
||||
Machine: cc-b2042074-46c3-4222-9d14-49c0c3637086-0
|
||||
GPU: Iluvatar BI-V100 32768MiB
|
||||
IX-ML: 3.2.3 | Driver: 3.2.1 | CUDA: 10.2
|
||||
|
||||
## 1. corex .so files
|
||||
|
||||
```
|
||||
find /usr/local/corex/ -name "libcorex_*.so" -ls 2>/dev/null
|
||||
# (empty — zero results)
|
||||
|
||||
find / -name "libcorex_gdn*" -ls 2>/dev/null
|
||||
# (empty — zero results)
|
||||
```
|
||||
|
||||
## 2. corex Python modules
|
||||
|
||||
```
|
||||
find / -name "corex_gdn.py" -ls 2>/dev/null
|
||||
# (empty)
|
||||
|
||||
find / -name "corex_moe.py" -ls 2>/dev/null
|
||||
# (empty)
|
||||
```
|
||||
|
||||
## 3. vllm models directory
|
||||
|
||||
```
|
||||
ls -la /usr/local/corex/lib/python3/dist-packages/vllm/model_executor/models/ | grep -i "corex\|qwen3_5"
|
||||
# (empty — neither corex modules nor qwen3_5.py in base image)
|
||||
```
|
||||
|
||||
## 4. All corex-named files in SDK
|
||||
|
||||
```
|
||||
find /usr/local/corex/ -name "*corex*" -type f 2>/dev/null
|
||||
/usr/local/corex/bin/corex-uninstaller
|
||||
/usr/local/corex/lib64/clang/16/include/__clang_cuda_ivcorex_intrinsics.h
|
||||
/usr/local/corex/lib64/python3/dist-packages/paddle/include/paddle/phi/core/corex.h
|
||||
/usr/local/corex/lib64/python3/dist-packages/torch/__pycache__/corex.cpython-310.pyc
|
||||
/usr/local/corex/lib64/python3/dist-packages/torch/corex.py
|
||||
/usr/local/corex/release-corex.txt
|
||||
```
|
||||
|
||||
## 5. Available .so libraries
|
||||
|
||||
```
|
||||
find /usr/local/corex/lib64/ -name "*.so" 2>/dev/null | head -30
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.asan.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.dyndd.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.hwasan.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.hwasan_aliases.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.memprof.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.scudo_standalone.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_minimal.so
|
||||
/usr/local/corex/lib64/clang/16/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone.so
|
||||
/usr/local/corex/lib64/libLTO.so
|
||||
/usr/local/corex/lib64/libclang.so
|
||||
/usr/local/corex/lib64/libRemarks.so
|
||||
/usr/local/corex/lib64/libclang-cpp.so
|
||||
/usr/local/corex/lib64/libcublas.so
|
||||
/usr/local/corex/lib64/libcublasLt.so
|
||||
/usr/local/corex/lib64/libcuda.so
|
||||
/usr/local/corex/lib64/libcudart.so
|
||||
/usr/local/corex/lib64/libcudnn.so
|
||||
/usr/local/corex/lib64/libcufft.so
|
||||
/usr/local/corex/lib64/libcufftw.so
|
||||
/usr/local/corex/lib64/libcuinfer.so
|
||||
/usr/local/corex/lib64/libcupti.so
|
||||
/usr/local/corex/lib64/libcurand.so
|
||||
/usr/local/corex/lib64/libcusolver.so
|
||||
/usr/local/corex/lib64/libcusparse.so
|
||||
/usr/local/corex/lib64/libcutlass.so
|
||||
/usr/local/corex/lib64/libibverbs.so
|
||||
/usr/local/corex/lib64/libixToolsExt.so
|
||||
/usr/local/corex/lib64/libixattn.so
|
||||
/usr/local/corex/lib64/libixkninject.so
|
||||
```
|
||||
|
||||
## 6. qwen3_5.py in base image
|
||||
|
||||
```
|
||||
find / -name "qwen3_5.py" -ls 2>/dev/null
|
||||
# (empty — not in base image, must be deployed by us)
|
||||
```
|
||||
|
||||
## 7. ixformer API
|
||||
|
||||
```python
|
||||
import ixformer
|
||||
# Full dir() output:
|
||||
['AVG', 'AddFunction', 'Any', 'BnbDequantFunction', 'BnbDoubleQuantFunction',
|
||||
'BnbMmDequantFunction', 'BnbQGemmFunction', 'BnbQuantFunction',
|
||||
'BnbRowColAbsMaxFunction', 'ChatGLM', 'ChunkFunction', 'ConcatFunction',
|
||||
'ContextBase', 'Contiguous', 'Copy', 'CudaStream', 'DataType', 'Device',
|
||||
'DeviceType', 'GLM130B', 'GPT2', 'GeluFunction', 'GptAttention', 'LLaMa',
|
||||
'LLaMaPipeline', 'List', 'MAX', 'MIN', 'MatmulFunction',
|
||||
'MemoryAllocatorType', 'MemoryFormat', 'MulFunction', 'Optional', 'PROD',
|
||||
'ParallelGpt', 'Permute', 'ReduceOp', 'ReductionSum', 'Reshape', 'SUM',
|
||||
'SplitFunction', 'Stream', 'StreamContext', 'SubFunction', 'Tensor',
|
||||
'TensorBase', 'TensorLayout', 'TensorOptions', 'TensorParallelLlama',
|
||||
'ToDevice', 'Transpose', 'Tuple', 'UndefinedTensor', 'Union', 'View',
|
||||
'_C', '_ixformer_torch', '_tensor',
|
||||
'act_bias_mm', 'add', 'allocate_memory', 'as_subclass',
|
||||
'attention_kv_cache_concat', 'attention_masked_softmax', 'autograd',
|
||||
'bfloat16', 'bnb_dequant', 'bnb_double_quant', 'bnb_mm_dequant',
|
||||
'bnb_qgemm', 'bnb_quant', 'bnb_rowcol_absmax', 'bool', 'byte',
|
||||
'can_device_access_peer', 'cat', 'channels_last', 'channels_last3d',
|
||||
'char', 'chunk', 'concat', 'contiguous', 'contiguous_format', 'contrib',
|
||||
'conv2d', 'copy', 'cuda', 'current_device', 'current_stream',
|
||||
'default_stream', 'device', 'device_count', 'device_synchronize',
|
||||
'distributed', 'double', 'dtype', 'elementwise', 'empty', 'empty_like',
|
||||
'empty_memory_caching', 'enable_grad', 'fill',
|
||||
'flash_attn', 'flash_attn_func', 'flash_attn_lib',
|
||||
'flash_attn_padded_func', 'flash_attn_varlen_func',
|
||||
'float', 'float16', 'free_memory', 'from_data_ptr', 'from_numpy',
|
||||
'from_torch', 'full', 'full_like', 'functions',
|
||||
'fused_add_rms_norm', 'gather_last_token_logits', 'geglu', 'gelu',
|
||||
'gelu_and_mul', 'gemv', 'gen_rotary_emb_weight',
|
||||
'get_arch_list', 'get_default_dtype', 'get_device_capability',
|
||||
'get_device_name', 'get_device_properties', 'get_gencode_flags',
|
||||
'get_memory_allocator', 'get_memory_allocator_type', 'get_tensor_ref_obj',
|
||||
'glm', 'glm2_rotary_embedding', 'glm_multi_query_repeat_key_value',
|
||||
'glm_multi_query_split_qkv', 'glm_split_qkv', 'gpt_attention',
|
||||
'group_norm', 'groupnorm', 'half', 'init_ixformer_context',
|
||||
'init_ixformer_modules', 'int', 'int32', 'int4WeightCompression',
|
||||
'int4WeightExtractionHalf', 'int64', 'int8', 'int8WeightExtractionHalf',
|
||||
'ipc_collect', 'is_available', 'is_differentiable_type', 'is_grad_enabled',
|
||||
'is_tensor', 'ixdnn_flash_attn_pad', 'ixdnn_flash_attn_unpad',
|
||||
'ixformer', 'ixinfer_flash_attn_pad', 'ixinfer_flash_attn_unpad',
|
||||
'kCPU', 'kCUDA', 'kCaching', 'kCustom', 'kNumDeviceType',
|
||||
'kNumMemoryAllocatorType', 'kNumReduceOp', 'kRaw', 'kUnknown',
|
||||
'kv_cache_concat', 'layernorm', 'lightllm', 'lightllm_apply_penalty',
|
||||
'lightllm_destindex_copy_kv', 'lightllm_glm2_rope',
|
||||
'lightllm_tokenattention', 'linalg', 'linear', 'linear_allreduce',
|
||||
'linear_allreduce_sum', 'linear_i8w8o32', 'llama_rotary_embedding',
|
||||
'masked_softmax', 'matmul', 'mul', 'new_tensor', 'no_grad',
|
||||
'num_data_type', 'num_memory_format', 'num_tensor_layout', 'ones',
|
||||
'ones_like', 'os', 'parse_kwargs', 'permute', 'preserve_format', 'qint8',
|
||||
'quantized_linear', 'quantized_weight_dequant', 'quint8', 'reduction',
|
||||
'reshape', 'residual_bias', 'residual_bias_ln', 'rms_norm',
|
||||
'rotary_embedding', 'rotary_embedding_2d',
|
||||
'scaled_dot_product_attention', 'set_custom_memory_allocator',
|
||||
'set_default_dtype', 'set_device', 'set_grad_enabled',
|
||||
'set_memory_allocator', 'set_stream', 'set_tensor_ref_obj',
|
||||
'silu_and_mul', 'skip_layer_norm', 'softmax', 'solve', 'split', 'stream',
|
||||
'stream_synchronize', 'strided', 'sub', 'sum', 'synchronize',
|
||||
't5', 't5_split_qkv', 't5_split_qkv_update_kv_cache', 'tensor', 'tgi',
|
||||
'tgi_apply_rotary', 'tgi_apply_rotary_emb_torch', 'to', 'torch_lib',
|
||||
'transpose', 'trt_llm_gpt_attention', 'uint32', 'uint64', 'uint8',
|
||||
'utils', 'view', 'vllm',
|
||||
'vllm_cache_ops_reshape_and_cache', 'vllm_copy_cache', 'vllm_gptq_shuffle',
|
||||
'vllm_llama_mlp', 'vllm_rotary_embedding_neox',
|
||||
'vllm_single_query_cached_kv_attention',
|
||||
'vllm_single_query_cached_kv_attention_v2',
|
||||
'vllm_smooth_dequant', 'vllm_smooth_dequant_add_residual',
|
||||
'vllm_smooth_dequant_fused_add_rms_norm_quant',
|
||||
'vllm_smooth_dequant_rotary_embedding_neox',
|
||||
'vllm_smooth_dequant_silu_and_mul_quant',
|
||||
'vllm_smooth_fused_add_rms_norm_quant', 'vllm_smooth_quant',
|
||||
'vllm_smooth_rms_norm_quant', 'vllm_swap_blocks',
|
||||
'w8a16', 'zeros', 'zeros_like']
|
||||
```
|
||||
|
||||
## 8. ixformer function signatures (confirmed)
|
||||
|
||||
```
|
||||
flash_attn_func(q, k, v, dropout_p=0.0, softmax_scale=None, causal=False, return_attn_probs=False)
|
||||
flash_attn_varlen_func(q, k, v, cu_seqlens_q, cu_seqlens_k, max_seqlen_q, max_seqlen_k, dropout_p=0.0, softmax_scale=None, causal=False, return_attn_probs=False, out=None)
|
||||
conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1)
|
||||
fused_add_rms_norm(input, residual, weight, eps=1e-05, scale=1.0)
|
||||
silu_and_mul(input, output=None)
|
||||
gemv(x, A)
|
||||
matmul(input, other, *, out=None, transa=False, transb=False, alpha=1.0, beta=0.0)
|
||||
rms_norm(input, weight, output=None, eps=1e-06)
|
||||
softmax(input, dim=None, _stacklevel=3, dtype=None, output=None)
|
||||
scaled_dot_product_attention(query, key, value, attn_mask=None, dropout_p=0.0, is_causal=False)
|
||||
```
|
||||
|
||||
## 9. ixformer.vllm submodule
|
||||
|
||||
```
|
||||
['CF', 'CacheOpsReshapeCacheFunction', 'Function', 'FunctionCtx',
|
||||
'RotaryEmbeddingNeoxFunction', 'Union',
|
||||
'compatible_torch_function', 'ixformer', 'ixformer_torch_ops', 'torch',
|
||||
'vllm_cache_ops_reshape_and_cache', 'vllm_copy_cache', 'vllm_gptq_shuffle',
|
||||
'vllm_llama_mlp', 'vllm_rotary_embedding_neox',
|
||||
'vllm_single_query_cached_kv_attention',
|
||||
'vllm_single_query_cached_kv_attention_v2',
|
||||
'vllm_smooth_dequant', 'vllm_smooth_dequant_add_residual',
|
||||
'vllm_smooth_dequant_fused_add_rms_norm_quant',
|
||||
'vllm_smooth_dequant_rotary_embedding_neox',
|
||||
'vllm_smooth_dequant_silu_and_mul_quant',
|
||||
'vllm_smooth_fused_add_rms_norm_quant', 'vllm_smooth_quant',
|
||||
'vllm_smooth_rms_norm_quant', 'vllm_swap_blocks']
|
||||
```
|
||||
|
||||
## 10. topk/moe/expert/gate related ops
|
||||
|
||||
```
|
||||
# (empty — zero topk/moe/expert/gate ops in ixformer)
|
||||
```
|
||||
|
||||
## 11. Compilation toolchain
|
||||
|
||||
```
|
||||
/usr/local/corex/lib64/clang/16/ — CUDA/C++ compiler
|
||||
libcublas.so, libcublasLt.so — BLAS
|
||||
libcuda.so, libcudart.so — CUDA runtime
|
||||
libcudnn.so — cuDNN
|
||||
libcutlass.so — CUTLASS
|
||||
libcufft.so, libcusolver.so — math libs
|
||||
libixattn.so — ixformer attention kernel
|
||||
```
|
||||
@@ -8,14 +8,14 @@ command:
|
||||
- --served-model-name
|
||||
- llm
|
||||
- --max-model-len
|
||||
- '100000'
|
||||
- '80000'
|
||||
- --gpu-memory-utilization
|
||||
- '0.9'
|
||||
- --trust-remote-code
|
||||
- -tp
|
||||
- '4'
|
||||
- --max-num-seqs
|
||||
- '1'
|
||||
- '2'
|
||||
- --disable-log-requests
|
||||
- --disable-frontend-multiprocessing
|
||||
- --enforce-eager
|
||||
|
||||
@@ -66,13 +66,25 @@ else
|
||||
echo "[patch_ops] WARNING: transformers/models not found"
|
||||
fi
|
||||
|
||||
# 1b. CoreX API probe — MUST run BEFORE deploying our qwen3_5.py
|
||||
# Discovers corex_gdn.py, corex_moe.py, corex_fa2.py interfaces from base image.
|
||||
# Also inspects native qwen3_5.py before we overwrite it.
|
||||
# Results go to /workspace/corex_probe_result.json + build log.
|
||||
echo "[patch_ops] Running CoreX API probe..."
|
||||
python3 ./probe_corex_api.py 2>&1
|
||||
echo "[patch_ops] CoreX probe done (see above for results)"
|
||||
# 1b. CoreX probe — direct shell, guaranteed to show in build log
|
||||
echo "[probe] === CoreX .so files ==="
|
||||
ls -la /usr/local/corex/lib64/libcorex_*.so 2>/dev/null || echo "[probe] NO .so files in /usr/local/corex/lib64/"
|
||||
echo "[probe] === CoreX Python wrappers ==="
|
||||
ls -la "$VLLM/model_executor/models/corex_"*.py 2>/dev/null || echo "[probe] NO corex_*.py in $VLLM/model_executor/models/"
|
||||
echo "[probe] === Native qwen3_5.py ==="
|
||||
if [ -f "$VLLM/model_executor/models/qwen3_5.py" ]; then
|
||||
wc -lc "$VLLM/model_executor/models/qwen3_5.py"
|
||||
grep -c "corex_gdn\|corex_moe\|CoreXGDN" "$VLLM/model_executor/models/qwen3_5.py" || echo "[probe] no corex refs"
|
||||
else
|
||||
echo "[probe] qwen3_5.py NOT in base image"
|
||||
fi
|
||||
echo "[probe] === All model files (corex related) ==="
|
||||
find "$VLLM" -name "*corex*" -type f 2>/dev/null || echo "[probe] zero corex files anywhere in vllm"
|
||||
echo "[probe] === LD_LIBRARY_PATH ==="
|
||||
echo "$LD_LIBRARY_PATH"
|
||||
echo "[probe] === /usr/local/corex/ tree ==="
|
||||
find /usr/local/corex/lib64/ -name "*.so" 2>/dev/null | head -20 || echo "[probe] no .so in corex lib64"
|
||||
echo "[probe] ==========================="
|
||||
|
||||
# 2. Model module — qwen3_5.py with CoreX dispatch (CCCL env_dispatch pattern).
|
||||
# Our version tries to import corex_gdn/corex_moe from the base image.
|
||||
@@ -163,6 +175,6 @@ if [ -n "$VLLM2" ]; then
|
||||
cp ./chat_utils.py "$VLLM2/entrypoints/chat_utils.py" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "[patch_ops] DONE — CoreX dispatch + serving layer + engine patches deployed"
|
||||
echo "[patch_ops] Deployed: qwen3_5.py(CoreX dispatch), paged_attn.py, mamba_cache.py, sequence.py, scheduler.py, xformers patches, tool/reasoning parsers, serving layer"
|
||||
echo "[patch_ops] NOT deployed (base image native): model_runner.py, _custom_ops.py, sampler.py, logits_processor.py, arg_utils.py"
|
||||
echo "[patch_ops] DONE — all patches deployed"
|
||||
echo "[patch_ops] Deployed: qwen3_5.py, paged_attn.py, mamba_cache.py, sequence.py, scheduler.py, xformers patches, tool/reasoning parsers, serving layer"
|
||||
echo "[patch_ops] NOT deployed (using base image native): model_runner.py, _custom_ops.py, sampler.py, logits_processor.py, arg_utils.py"
|
||||
|
||||
@@ -44,16 +44,33 @@ from vllm.model_executor.models.interfaces import HasInnerState, SupportsLoRA
|
||||
logger = init_logger(__name__)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# CoreX dispatch probe (CCCL env_dispatch pattern)
|
||||
# ixformer hardware acceleration (BI-V100 native ops)
|
||||
#
|
||||
# The base Docker image contains fused CUDA kernels for BI-V100:
|
||||
# corex_gdn.py — GatedDeltaNet fused prefill/decode
|
||||
# corex_moe.py — MoE fused prefill/decode (expert-grouped-wmma)
|
||||
# These are loaded from .so files specified by env vars:
|
||||
# VLLM_COREX_GDN_LIBRARY, VLLM_COREX_MOE_LIBRARY
|
||||
# Confirmed available on BI-V100 via SSH probe (Aug 8 2026):
|
||||
# ixformer.matmul(input, other, out=None, transa=False, transb=False, alpha=1.0, beta=0.0)
|
||||
# ixformer.softmax(input, dim=None)
|
||||
# ixformer.rms_norm(input, weight, output=None, eps=1e-6)
|
||||
# ixformer.fused_add_rms_norm(input, residual, weight, eps=1e-5, scale=1.0)
|
||||
# ixformer.silu_and_mul(input, output=None)
|
||||
# ixformer.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1)
|
||||
# ixformer.flash_attn_func(q, k, v, dropout_p=0.0, softmax_scale=None, causal=False)
|
||||
# ixformer.gemv(x, A)
|
||||
#
|
||||
# If import fails, we fall back to pure PyTorch (10x slower but correct).
|
||||
# No topk/moe/expert/gate ops available — MoE stays pure PyTorch.
|
||||
# No fused GDN scan kernel — GDN loop stays, but individual ops inside are accelerated.
|
||||
# ---------------------------------------------------------------------------
|
||||
_ix = None
|
||||
_ix_available = False
|
||||
|
||||
try:
|
||||
import ixformer as _ix
|
||||
_ix_available = True
|
||||
logger.info("ixformer loaded — BI-V100 hardware acceleration available")
|
||||
except ImportError:
|
||||
logger.warning("ixformer not found — using pure PyTorch (no hardware acceleration)")
|
||||
|
||||
# corex_gdn/corex_moe: these are custom modules that teams package into their
|
||||
# Docker image. If present, they provide fused GDN/MoE kernels.
|
||||
_corex_gdn_module = None
|
||||
_corex_moe_module = None
|
||||
_corex_gdn_available = False
|
||||
@@ -62,20 +79,52 @@ _corex_moe_available = False
|
||||
try:
|
||||
from vllm.model_executor.models import corex_gdn as _corex_gdn_module
|
||||
_corex_gdn_available = True
|
||||
logger.info("CoreX GDN module imported successfully — fused GDN kernels available")
|
||||
logger.info("CoreX GDN module found — fused GDN kernels available")
|
||||
except ImportError:
|
||||
logger.warning("CoreX GDN module not found — using pure PyTorch GDN (slower)")
|
||||
pass # expected if not packaged; ixformer ops used instead
|
||||
|
||||
try:
|
||||
from vllm.model_executor.models import corex_moe as _corex_moe_module
|
||||
_corex_moe_available = True
|
||||
logger.info("CoreX MoE module imported successfully — fused MoE kernels available")
|
||||
logger.info("CoreX MoE module found — fused MoE kernels available")
|
||||
except ImportError:
|
||||
logger.warning("CoreX MoE module not found — using pure PyTorch MoE (slower)")
|
||||
pass # expected; MoE uses PyTorch loop
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pure-PyTorch DeltaNet kernels (fallbacks from transformers 5.2.0)
|
||||
# ixformer-accelerated ops (drop-in replacements for torch ops)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _ix_matmul(a: torch.Tensor, b: torch.Tensor) -> torch.Tensor:
|
||||
"""BI-V100 accelerated matmul via ixformer, fallback to torch."""
|
||||
if _ix_available:
|
||||
try:
|
||||
return _ix.matmul(a, b)
|
||||
except Exception:
|
||||
pass
|
||||
return torch.matmul(a, b)
|
||||
|
||||
def _ix_bmm(a: torch.Tensor, b: torch.Tensor) -> torch.Tensor:
|
||||
"""Batched matmul — ixformer.matmul handles batched inputs."""
|
||||
if _ix_available:
|
||||
try:
|
||||
return _ix.matmul(a, b)
|
||||
except Exception:
|
||||
pass
|
||||
return torch.matmul(a, b)
|
||||
|
||||
def _ix_softmax(x: torch.Tensor, dim: int = -1) -> torch.Tensor:
|
||||
"""BI-V100 accelerated softmax via ixformer."""
|
||||
if _ix_available:
|
||||
try:
|
||||
return _ix.softmax(x, dim=dim)
|
||||
except Exception:
|
||||
pass
|
||||
return torch.softmax(x, dim=dim)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pure-PyTorch DeltaNet kernels (with ixformer acceleration where possible)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _l2norm(x: torch.Tensor, dim: int = -1, eps: float = 1e-6) -> torch.Tensor:
|
||||
@@ -143,16 +192,21 @@ def _torch_chunk_gated_delta_rule(
|
||||
torch.ones(chunk_size, chunk_size, dtype=torch.bool, device=query.device),
|
||||
diagonal=0)
|
||||
|
||||
# CCCL accumulator_t pattern: clamp BEFORE cumsum to prevent overflow
|
||||
# at the source. Without this, individual g values of ±10 accumulate
|
||||
# over 64 positions to ±640 — far beyond float32 exp() safe range (~88).
|
||||
g = g.clamp(-5.0, 2.0)
|
||||
g = g.cumsum(dim=-1)
|
||||
g = g.clamp(-20.0, 20.0)
|
||||
decay_mask = ((g.unsqueeze(-1) - g.unsqueeze(-2)).tril().exp().float()).tril()
|
||||
attn = -((k_beta @ key.transpose(-1, -2)) * decay_mask).masked_fill(mask_upper, 0)
|
||||
attn = -((_ix_matmul(k_beta, key.transpose(-1, -2))) * decay_mask).masked_fill(mask_upper, 0)
|
||||
for i in range(1, chunk_size):
|
||||
row = attn[..., i, :i].clone()
|
||||
sub = attn[..., :i, :i].clone()
|
||||
attn[..., i, :i] = row + (row.unsqueeze(-1) * sub).sum(-2)
|
||||
attn = attn + torch.eye(chunk_size, dtype=attn.dtype, device=attn.device)
|
||||
value = attn @ v_beta
|
||||
k_cumdecay = attn @ (k_beta * g.exp().unsqueeze(-1))
|
||||
value = _ix_matmul(attn, v_beta)
|
||||
k_cumdecay = _ix_matmul(attn, k_beta * g.clamp(-20, 20).exp().unsqueeze(-1))
|
||||
|
||||
last_state = (
|
||||
torch.zeros(batch, num_heads, k_dim, v_dim, dtype=value.dtype, device=value.device)
|
||||
@@ -166,15 +220,16 @@ def _torch_chunk_gated_delta_rule(
|
||||
|
||||
for i in range(total_len // chunk_size):
|
||||
q_i, k_i, v_i = query[:, :, i], key[:, :, i], value[:, :, i]
|
||||
attn_i = (q_i @ k_i.transpose(-1, -2) * decay_mask[:, :, i]).masked_fill_(mask_upper2, 0)
|
||||
v_prime = k_cumdecay[:, :, i] @ last_state
|
||||
attn_i = (_ix_matmul(q_i, k_i.transpose(-1, -2)) * decay_mask[:, :, i]).masked_fill_(mask_upper2, 0)
|
||||
v_prime = _ix_matmul(k_cumdecay[:, :, i], last_state)
|
||||
v_new = v_i - v_prime
|
||||
attn_inter = (q_i * g[:, :, i, :, None].exp()) @ last_state
|
||||
core_out[:, :, i] = attn_inter + attn_i @ v_new
|
||||
attn_inter = _ix_matmul(q_i * g[:, :, i, :, None].clamp(-20, 20).exp(), last_state)
|
||||
core_out[:, :, i] = attn_inter + _ix_matmul(attn_i, v_new)
|
||||
last_state = (
|
||||
last_state * g[:, :, i, -1, None, None].exp()
|
||||
+ (k_i * (g[:, :, i, -1, None] - g[:, :, i]).exp()[..., None])
|
||||
.transpose(-1, -2) @ v_new
|
||||
last_state * g[:, :, i, -1, None, None].clamp(-20, 20).exp()
|
||||
+ _ix_matmul(
|
||||
(k_i * (g[:, :, i, -1, None] - g[:, :, i]).clamp(-20, 20).exp()[..., None])
|
||||
.transpose(-1, -2), v_new)
|
||||
)
|
||||
|
||||
if not output_final_state:
|
||||
@@ -447,8 +502,11 @@ class GatedDeltaNet(nn.Module):
|
||||
v = v.reshape(1, seq_len, local_num_v, self.head_v_dim)
|
||||
|
||||
beta = b_all[s:e].sigmoid().unsqueeze(0) # (1, seq_len, local_num_v)
|
||||
g = (-self.A_log.float().exp()
|
||||
* F.softplus(a_all[s:e].float() + self.dt_bias)
|
||||
# CCCL overflow guard: clamp A_log before exp to prevent
|
||||
# extreme decay rates that cause cumsum → exp → NaN chain
|
||||
_A_safe = self.A_log.float().clamp(-8.0, 4.0)
|
||||
g = (-_A_safe.exp()
|
||||
* F.softplus(a_all[s:e].float() + self.dt_bias).clamp(max=10.0)
|
||||
).unsqueeze(0) # (1, seq_len, local_num_v)
|
||||
|
||||
# Expand k/q to match num_v_heads
|
||||
@@ -460,7 +518,7 @@ class GatedDeltaNet(nn.Module):
|
||||
# Full 18K: tensors [1,6,282,64,64]=220 MB each → ~990 MB/call.
|
||||
# With _DNN_CHUNK=4096: [1,6,64,64,64]=6 MB each → ~137 MB/call.
|
||||
# State is chained via initial_state / output_final_state.
|
||||
_DNN_CHUNK = 4096
|
||||
_DNN_CHUNK = 2048
|
||||
cur_state = temporal_state[si:si + 1].clone()
|
||||
core_out_parts = []
|
||||
for sc_start in range(0, seq_len, _DNN_CHUNK):
|
||||
@@ -522,8 +580,9 @@ class GatedDeltaNet(nn.Module):
|
||||
v = v.reshape(num_seqs, 1, local_num_v, self.head_v_dim)
|
||||
|
||||
beta = b_all.sigmoid().unsqueeze(1) # (num_seqs, 1, local_num_v)
|
||||
g = (-self.A_log.float().exp()
|
||||
* F.softplus(a_all.float() + self.dt_bias)
|
||||
_A_safe = self.A_log.float().clamp(-8.0, 4.0)
|
||||
g = (-_A_safe.exp()
|
||||
* F.softplus(a_all.float() + self.dt_bias).clamp(max=10.0)
|
||||
).unsqueeze(1) # (num_seqs, 1, local_num_v)
|
||||
|
||||
q = q.repeat_interleave(self.head_expand_ratio, dim=2)
|
||||
@@ -540,7 +599,7 @@ class GatedDeltaNet(nn.Module):
|
||||
q_t = _l2norm(q.squeeze(1)).float() * _scale # (B, H_v, k_dim)
|
||||
k_t = _l2norm(k.squeeze(1)).float() # (B, H_v, k_dim)
|
||||
v_t = v.squeeze(1).float() # (B, H_v, v_dim)
|
||||
g_t = g.squeeze(1).float().exp_() # (B, H_v)
|
||||
g_t = g.squeeze(1).float().clamp_(-20.0, 2.0).exp_() # (B, H_v) — clamp before exp
|
||||
bt = beta.squeeze(1).float() # (B, H_v)
|
||||
|
||||
# Decay state in-place: (B, H_v, k_dim, v_dim) *= scalar per head
|
||||
@@ -551,7 +610,7 @@ class GatedDeltaNet(nn.Module):
|
||||
BH = ts_flat.shape[0]
|
||||
|
||||
# kv_mem = k_t @ temporal_state shape: (B*H_v, 1, k_dim) @ (B*H_v, k_dim, v_dim)
|
||||
kv_mem = torch.bmm(
|
||||
kv_mem = _ix_bmm(
|
||||
k_t.view(BH, 1, self.head_k_dim), ts_flat
|
||||
).view(num_seqs, local_num_v, self.head_v_dim) # (B, H_v, v_dim)
|
||||
|
||||
@@ -564,7 +623,7 @@ class GatedDeltaNet(nn.Module):
|
||||
)
|
||||
|
||||
# Output: core_out = q_t @ updated temporal_state
|
||||
core_out = torch.bmm(
|
||||
core_out = _ix_bmm(
|
||||
q_t.view(BH, 1, self.head_k_dim), ts_flat
|
||||
).view(num_seqs, local_num_v, self.head_v_dim).to(orig_dtype)
|
||||
# core_out: (B, H_v, v_dim) = (num_seqs, local_num_v, head_v_dim) already
|
||||
@@ -849,7 +908,7 @@ class Qwen3_5MoeSparseBlock(nn.Module):
|
||||
with reduce_results=False.
|
||||
"""
|
||||
# Routing: softmax → topk → renormalise
|
||||
routing_weights = torch.softmax(router_logits.float(), dim=-1)
|
||||
routing_weights = _ix_softmax(router_logits.float(), dim=-1)
|
||||
topk_weights, topk_ids = torch.topk(
|
||||
routing_weights, self.top_k, dim=-1) # (T, top_k)
|
||||
topk_weights = topk_weights / topk_weights.sum(dim=-1, keepdim=True)
|
||||
@@ -881,7 +940,7 @@ class Qwen3_5MoeSparseBlock(nn.Module):
|
||||
act = F.silu(gate) * up # (K, I)
|
||||
|
||||
# bmm: (K,H,I) @ (K,I,1) → (K,H,1) → (K,H)
|
||||
expert_out = torch.bmm(w2_sel, act.unsqueeze(-1)).squeeze(-1) # (K, H)
|
||||
expert_out = _ix_bmm(w2_sel, act.unsqueeze(-1)).squeeze(-1) # (K, H)
|
||||
|
||||
out = (expert_out * ws.unsqueeze(-1)).sum(0, keepdim=True).to(
|
||||
hidden_states.dtype) # (1, H)
|
||||
|
||||
@@ -364,6 +364,12 @@ class OpenAIServingChat(OpenAIServing):
|
||||
except ValueError as e:
|
||||
# TODO: Use a vllm-specific Validation Error
|
||||
return self.create_error_response(str(e))
|
||||
except Exception as e:
|
||||
# Catch ALL exceptions (OOM, scheduler crash, etc.) to prevent
|
||||
# a single request from killing the entire engine process.
|
||||
logger.exception("Engine error (non-fatal, returning 500): %s", e)
|
||||
return self.create_error_response(
|
||||
f"Internal engine error: {type(e).__name__}: {e}")
|
||||
|
||||
if raw_request:
|
||||
result_generator = iterate_with_cancellation(
|
||||
|
||||
Reference in New Issue
Block a user