# P800 SGLang Profiling 报告

> 日期: 2026-07-20
> 实验目录: `/data1/yy/sskj/experiments/p800/dsv4_p800_sglang_profile/`
> 测试场景: ISL=4096, OSL=1024, Concurrency=16, TP=8, DP=1

---

## 一、实验目的

定位 P800 SGLang 与 H20 SGLang 在 DeepSeek-V4-Flash-INT8 模型推理上的性能差距根因。

**已知差距**（TP8/DP1, ISL=4k, OSL=1k, C=16）：

| 指标 | P800 | H20 | 差距 |
|:----|:---:|:---:|:----:|
| Total TPS | 1,863 | 4,866 | H20 快 2.6x |
| TPOT P50 | 37ms | 13ms | H20 快 2.8x |
| ITL P50 | 35ms | 11ms | H20 快 3.1x |
| E2E P95 | 49s | 17s | H20 快 2.9x |

---

## 二、实验环境

### 2.1 硬件

| 项目 | 配置 |
|:----|:----|
| 服务器 | p800.2 (gpu049) |
| XPU | 8× Kunlun P800 XPU, 96GB/XPU |
| 驱动版本 | 515.58 |

### 2.2 软件

| 项目 | 版本 |
|:----|:----|
| Docker 镜像 | `iregistry.baidu-int.com/xpu/sglang-p800-pd-disagg-0510:20260511_4202` |
| SGLang | 容器内预装版本 |
| PyTorch | 容器内预装版本 |
| 模型 | DeepSeek-V4-Flash-INT8 (INT8 量化) |
| 推理引擎 | SGLang (XPU 定制版) |

### 2.3 服务器启动参数

```
--host 0.0.0.0 --port 30015 --model-path /models
--attention-backend nsa --nsa-prefill klxdsa --nsa-decode klxdsa
--trust-remote-code --disable-custom-all-reduce --page-size 64
--mem-fraction-static 0.8 --tensor-parallel-size 8
--disable-shared-experts-fusion --quantization w8a8_int8
--kv-cache-dtype float16 --disable-piecewise-cuda-graph
--cuda-graph-max-bs 32 --watchdog-timeout 3000000
--tool-call-parser deepseekv4 --reasoning-parser deepseek-v4
--constrained-json-disable-any-whitespace
--enable-metrics --enable-request-time-stats-logging
--context-length 140000
```

### 2.4 关键 Patch

容器启动时挂载了以下 PATCH 文件（位于 `/data1/yy/sskj/platforms/patches/kunlun_p800/`）：

| Patch 文件 | 作用 |
|:----------|:-----|
| `hf_transformers_utils.py.patched` | 修复 DeepSeek-V4 模型架构识别 |
| `fp8_utils.py.patched` | FP8 量化工具修复 |
| `config_backup_small_w8a8_int8.json` | INT8 配置备份 |
| `parallel_state.py` | 分布式状态修复 |
| `vocab_parallel_embedding.py` | Embedding 并行修复 |
| `sitecustomize_xpu.py` | XPU 环境初始化 |
| `nic_priority_matrix_test.json` | 网络拓扑配置 |
| `bench_serving.py` (patched) | 增加 P95 TTFT/TPOT/E2E 指标输出 |

---

## 三、实验目录结构

```
/data1/yy/sskj/experiments/p800/dsv4_p800_sglang_profile/
├── config.env                  # 配置文件
├── start_sglang_docker.sh      # 容器启动脚本
├── run_profile.sh              # 一键 profile 运行脚本
├── patches/
│   └── bench_serving.py        # 已打补丁的 bench_serving
├── profile_output/             # Profile 输出目录
│   ├── <timestamp>/
│   │   ├── xpu_monitor.csv     # XPU 利用率监控
│   │   └── bench_serving.log   # Benchmark 日志
│   └── ...
├── bench_output/               # Benchmark 结果目录
│   └── results_no_profile.jsonl # 基准测试结果
└── runtime/
    ├── logs/                   # 服务器日志
    └── entrypoint_*.sh         # 容器启动入口脚本
```

---

## 四、PyTorch Profiler Bug

### 4.1 Bug 描述

SGLang bench_serving 的 `--profile` 功能使用 PyTorch Profiler 采集 GPU/XPU 的 kernel 执行 trace。在 P800 XPU 上，profiler 可以**启动并采集数据**，但在**停止保存 trace 时崩溃**，导致服务器进程被 kill。

### 4.2 错误信息

```
RuntimeError: [FATAL]
[/mnt/ssd3/xpytorch/workspace/.../cupti/cupti_activity.cpp:137:cuptiActivityDisable]
CUTOOL_CALL func pExportTable->etiEndEventSampling(ctx) failed with error 17
```

### 4.3 触发条件

- 使用 `--profile` 或 `--profile --profile-num-steps N` 启动 profiler
- Profiler 运行 N 步后尝试自动停止，或 benchmark 完成后客户端发送 stop_profile 请求
- 在 `cuptiActivityDisable()` 调用时崩溃

### 4.4 影响

- ❌ Chrome Trace JSON 文件无法生成
- ❌ 服务器进程被 kill（SIGKILL）
- ✅ 不影响非 profiler 模式的正常运行

### 4.5 根因

XPU 的 CUPTI（CUDA Profiling Tools Interface）实现在 `etiEndEventSampling` 调用时存在 bug，无法正确停止事件采样。这是 XPU 驱动/PyTorch XPU 后端的已知问题。

### 4.6 临时解决方案

1. **不使用 PyTorch Profiler**，改用 SGLang 内置的 `--enable-metrics` 和 `--enable-request-time-stats-logging` 获取聚合指标
2. 使用 `xpu-smi` 实时监控 XPU 利用率、显存、功耗
3. 使用 `--output-details` 获取每个请求的延迟分布
4. 在 H20 上使用同样的 profiler（NVIDIA 版本无此 bug）获取 Chrome Trace 做对比

---

## 五、测试过程记录

### 5.1 创建实验目录

```bash
# 创建目录
mkdir -p /data1/yy/sskj/experiments/p800/dsv4_p800_sglang_profile/patches

# 复制 patched bench_serving.py
cp /data1/yy/sskj/experiments/p800/dsv4_p800_sglang_tp_dp_matrix/patches/bench_serving.py \
   /data1/yy/sskj/experiments/p800/dsv4_p800_sglang_profile/patches/bench_serving.py

# 创建配置文件
# config.env: 基于 dsv4_p800_sglang_tp_dp_matrix 的配置，增加 PROFILE_OUTPUT_DIR 等
```

### 5.2 启动脚本要点

`start_sglang_docker.sh` 需要包含：

1. 所有必要的环境变量（`XPU_VISIBLE_DEVICES`, `SGLANG_DSV4_MODE` 等 30+ 个）
2. 所有必要的 Patch 挂载（8 个关键 patch 文件）
3. `XPU_ENABLE_PROFILER_TRACING=1` 环境变量（启用 profiler 的必要条件）
4. Profile 输出目录的挂载（`-v host_dir:/workspace/profile_output:rw`）
5. 使用独立容器名，避免与其他实验冲突

### 5.3 启动命令

```bash
# 方式1：一键运行
bash run_profile.sh

# 方式2：分步执行
bash start_sglang_docker.sh 8 1                # 启动服务器
docker exec ... sglang.bench_serving ...        # 运行 benchmark
docker rm -f sglang-dsv4-flash-profile          # 停止服务器
```

### 5.4 服务器启动耗时

从 `docker run` 到 `health check` 通过约需 **2分40秒**。

### 5.5 Benchmark 执行

```bash
docker exec sglang-dsv4-flash-profile \
  /root/miniconda/envs/python310_torch25_cuda/bin/python \
  -m sglang.bench_serving \
  --backend sglang --host 127.0.0.1 --port 30015 \
  --model /data1/models/DeepSeek-V4-Flash-INT8 \
  --dataset-name random --random-input-len 4096 \
  --random-output-len 1024 --random-range-ratio 1.0 \
  --num-prompts 80 --max-concurrency 16 --request-rate 10000 \
  --output-file /workspace/bench_output/results.jsonl --output-details
```

### 5.6 Profiler 调用（已确认不可用）

```bash
# 以下参数会导致 profiler 崩溃
--profile --profile-num-steps 30 \
--profile-output-dir /workspace/profile_output \
--profile-prefix p800_4k1k_c16
```

---

## 六、基准测试结果

### 6.1 本次测试结果

| 指标 | 数值 |
|:----|:----:|
| Successful requests | 80 |
| Benchmark duration (s) | 250.70 |
| Total input tokens | 327,680 |
| Total generated tokens | 81,920 |
| Request throughput (req/s) | 0.32 |
| Input token throughput (tok/s) | 1,306.97 |
| Output token throughput (tok/s) | 326.74 |
| Peak output token throughput (tok/s) | 464.00 |
| Peak concurrent requests | 32 |
| **Total token throughput (tok/s)** | **1,633.71** |
| Concurrency | 16.00 |

### 6.2 延迟分布

| 指标 | P50 | P95 | P99 |
|:----|:--:|:--:|:--:|
| E2E Latency (ms) | 49,422 | 53,409 | 53,410 |
| **TTFT (ms)** | **9,335** | **14,336** | **15,223** |
| **TPOT (ms)** | **40.4** | **45.9** | **46.4** |
| **ITL (ms)** | **34.9** | **53.4** | **58.4** |
| Max ITL (ms) | 9,895 | | |

### 6.3 XPU 监控

| 指标 | 数值 |
|:----|:----:|
| XPU 利用率 P50 | 95% |
| 显存使用率 | 98.5% (96GB/XPU 几乎占满) |

---

## 七、与 H20 的对比分析

### 7.1 同配置对比（TP8/DP1, C=16, ISL=4k, OSL=1k）

| 指标 | P800 | H20 | 差距 | 瓶颈类型 |
|:----|:---:|:---:|:----:|:--------:|
| Total TPS | 1,634 | 4,866 | 3.0x | 综合 |
| TTFT P95 | 14,336ms | 5,341ms | 2.7x | Prefill (计算) |
| TPOT P50 | 40.4ms | 13.1ms | **3.1x** | **Decode (内存带宽)** |
| ITL P50 | 34.9ms | 11.2ms | 3.1x | Decode (内存带宽) |
| ITL P95 | 53.4ms | 11.5ms | 4.6x | Decode 稳定性 |
| ITL Max | 9,895ms | — | — | 调度抖动 |

### 7.2 核心瓶颈分析

**Decode 阶段（TPOT/ITL）是最大差距所在**，差距约 3.1x。即使在没有并发竞争的 C=1 场景下，P800 的 TPOT 也高达 26.6ms，而 H20 仅 9.1ms。

**根本原因：**

1. **内存带宽不足**（最主要）
   - LLM decode 是 memory-bound 操作
   - P800 XPU 的 HBM 带宽可能远低于 H20 的 4.0 TB/s HBM3
   - 即使 INT8 量化减少了一半数据量，带宽仍然不够

2. **Kernel 效率低**
   - NSA attention 等定制 kernel 在 XPU 上的优化程度不如 CUDA
   - ITL 波动大（P95=53.4ms vs P50=34.9ms），说明 kernel 执行不稳定

3. **通信开销大**
   - TP=8 需要 8 张 XPU 做 all-reduce
   - XPULINK 互联带宽可能低于 NVLink

4. **显存瓶颈**
   - 显存使用率 98.5%，几乎没有余量
   - 限制了 batch size 和内存管理效率

---

## 八、实验文件清单

| 文件 | 路径 | 说明 |
|:----|:----|:-----|
| config.env | `dsv4_p800_sglang_profile/config.env` | 实验配置 |
| start_sglang_docker.sh | `dsv4_p800_sglang_profile/start_sglang_docker.sh` | 容器启动脚本 |
| run_profile.sh | `dsv4_p800_sglang_profile/run_profile.sh` | 一键运行脚本 |
| bench_serving.py (patched) | `dsv4_p800_sglang_profile/patches/bench_serving.py` | 打补丁的 bench_serving |
| 基准测试结果 | `dsv4_p800_sglang_profile/bench_output/results_no_profile.jsonl` | 80请求的benchmark结果 |
| 服务器日志 | `dsv4_p800_sglang_profile/runtime/logs/` | 服务器启动日志 |

---

## 九、后续建议

1. **在 H20 上跑同样的 profile**（使用 `--profile --profile-num-steps 30`），获取 Chrome Trace 文件，与 P800 做 kernel 级别的对比
2. **降低 TP 度数**：尝试 TP4/DP2 代替 TP8/DP1，减少通信开销
3. **升级 XPU 驱动**：修复 `cuptiActivityDisable` bug 后重新尝试 PyTorch Profiler
4. **添加手动计时**：在 SGLang 的 decode loop 中添加分段计时（attention vs MoE vs all-reduce），绕过 profiler 的限制