Files
xserv/README.md
Gahow Wang 11e0154e4d docs: Phase 18 pipeline parallelism — design + benchmark results
docs/18-pipeline-parallelism.md: PP design (layer split, NCCL P2P,
per-stage KV, engine/threading model).
docs/benchmarks/pp-sweep.md: measured on dash5 (8x RTX 5090, Qwen3-8B
BF16) — single-stream latency + per-GPU VRAM (~1/N), byte-exact
correctness (single x2 vs pp4 x2 control), and the full AIME-30 +
GSM8K-30 quality matrix (xserv & llama.cpp PP=1/2/4): GSM8K 29/30 in
every cell, TPOT flat across PP.
README: multi-card (TP/PP) section + roadmap to Phase 18.
gitignore: /.claude/ runtime state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 18:57:09 +08:00

198 lines
8.3 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.

# xserv
> 从零用 **Rust + CUDA** 构建的 LLM 推理引擎,目标是吃透 LLM Serving 全栈技术。
xserv 不依赖 PyTorch / vLLM / TensorRT 等现成框架自己实现了张量抽象、CUDA kernel、
分词器、模型前向、KV cache、调度器和 OpenAI 兼容的 HTTP 服务。当前在单张 RTX 5090 上可以
跑通 **Qwen3-8B**BF16并提供一套与 **llama.cpp** 对比正确性和性能的标准 benchmark。
## 现状一览
- **模型**GPT-2124M、Qwen3-8BBF16
- **性能**RTX 5090Qwen3-8B BF16贪心解码单流**56 tok/s**,约为 HF transformers 的 1.4×、llama.cpp 的 ~0.6×
- **精度**:在 AIME 2025 / GSM8K 上与 llama.cpp 同权重对比基本持平(数值保真度验证通过)
- **服务**OpenAI 兼容 `/v1/chat/completions`,支持 SSE 流式输出
- **关键能力**:自写 GEMM / Flash-Attention 2(SM120) / Paged-Attention kernel、
分页 KV cache**CPU 换出/换入** 弹性显存、连续批处理continuous batching
CUDA Graph 解码、按显存自适应的 KV 池
> 这是一个以学习为主的项目,逐 Phase 推进,每步都做数值/端到端验证。
## 架构
```
xserv/
├── csrc/ # CUDA 源码 (.cu/.cuh)
│ ├── gemm/ # GEMM (naive / tiled / gemv)
│ ├── attention/ # Flash-Attention 2 (SM120)、Paged-Attention、causal mask
│ ├── normalization/ # LayerNorm / RMSNorm
│ ├── activation/ # GELU / SiLU
│ ├── embedding/ # embedding lookup / RoPE / transpose
│ └── reduce/ # softmax
├── crates/
│ ├── xserv-cuda/ # CUDA FFI、Stream、显存分配器、Pinned 内存、CUDA Graph
│ ├── xserv-tensor/ # Tensor 类型strided 布局、BF16/F16/F32、CPU↔GPU
│ ├── xserv-kernels/ # kernel registry自写 kernel + cuBLAS 可切换)
│ ├── xserv-tokenizer/ # BPE 分词器
│ ├── xserv-model/ # 模型定义GPT-2 / Qwen3、权重加载、KV cache、采样
│ └── xserv-server/ # tokio + axum HTTP 服务、调度器
├── tools/ # 辅助脚本 + benchmark 套件(见下)
└── docs/ # 每个 Phase 的设计文档 + benchmark 报告
```
## 环境要求
- **GPU**NVIDIA计算能力 SM120RTX 5090 / Blackwell。其它架构需调整 `CUDA_ARCH`
- **CUDA Toolkit**12.9`nvcc` 需在 `PATH`,构建 `.cu` 依赖它)
- **Rust**edition 2024建议较新的 stable 工具链)
- **模型**HuggingFace 目录格式(含 `config.json``tokenizer.json``*.safetensors`
## 构建
```bash
export CUDA_HOME=/usr/local/cuda-12.9
export PATH=$CUDA_HOME/bin:$PATH
cargo build --release
```
如果本地没有 GPU/CUDA可用远端构建脚本把代码同步到带卡的机器上构建/运行/测试:
```bash
./tools/sync-and-build.sh build # 远端 cargo build --release
./tools/sync-and-build.sh test # 远端 cargo test
```
(远端主机、目录、模型路径在 `tools/sync-and-build.sh` 顶部配置。)
## 基本用法
### 1. 启动 HTTP 服务OpenAI 兼容)
```bash
./target/release/xserv-server /path/to/qwen3-8b \
--port 8080 \
--max-batch 4 \
--max-seq-len 8192 \
--swap-space-gb 8
```
参数说明:
| 参数 | 含义 | 默认 |
|------|------|------|
| `--port` | 监听端口 | 8080 |
| `--max-batch` | 解码批大小(并发上限) | 4 |
| `--max-seq-len` | 单序列最大长度 | 2048 |
| `--swap-space-gb` | KV 换出到 CPU 的 pinned 内存大小0 关闭) | 8 |
请求示例(流式):
```bash
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3-8b",
"messages": [{"role": "user", "content": "用一句话解释什么是注意力机制"}],
"max_tokens": 256,
"temperature": 0,
"stream": true
}'
```
其它端点:`GET /health``GET /v1/models`
### 2. 命令行推理
```bash
# 单轮生成
cargo run --release --bin xserv-cli -- /path/to/qwen3-8b --max-tokens 256
# 交互式多轮对话
cargo run --release --bin xserv-chat -- /path/to/qwen3-8b
```
### 3. 单机性能基准
```bash
# 输出每个 prompt 的 TTFT / TBT / TPOTJSON
cargo run --release --bin bench-qwen3 -- /path/to/qwen3-8b --gen-tokens 64 [--cuda-graph]
```
## 与 llama.cpp 对比 benchmark
`tools/bench/` 提供一套一键对比套件,把 xserv 和 **llama.cpp**(同一份 BF16 权重)放在
相同负载下,黑盒通过 OpenAI API 对比:
- **性能**TTFT、TPOT、吞吐单流 + 不同并发)
- **精度**AIME 2025、GSM8K标准数据集exact-match 评分)
```bash
# 一次性准备(需联网的机器):拉取 llama.cpp 子模块 + 下载数据集
git submodule update --init third_party/llama.cpp # 固定在 tag b9371
HF_ENDPOINT=https://hf-mirror.com python3 -m tools.bench.fetch_datasets
# 一键对比(构建 llama.cpp + 转 GGUF + 构建 xserv + 跑两套 + 出报告)
./tools/sync-and-build.sh bench -- --max-seq-len 8192 --quality-limit 50
./tools/sync-and-build.sh fetch-bench-out
# 报告产物bench-out/comparison-<时间戳>.{md,json}
```
设计细节见 `docs/16-llama-cpp-comparison.md`,结果报告见 `docs/benchmarks/llama-cpp-comparison.md`
## 文档
- `docs/00-roadmap.md`:总体路线图与各 Phase 设计
- `docs/01..15-*.md`CUDA FFI / Tensor / GEMM / Attention / KV cache / 性能优化等每个 Phase 的设计文档
- `docs/16-llama-cpp-comparison.md`llama.cpp 对比基准的设计
- `docs/17-tensor-parallelism.md`张量并行TP设计
- `docs/18-pipeline-parallelism.md`流水线并行PP设计
- `docs/benchmarks/`:各阶段的 benchmark 报告(含 `pp-sweep.md`
## 多卡并行TP / PP
单机多卡,复用 NCCLcrate `xserv-distributed`)。两种切法正交、二选一:
- **张量并行 `--tp N`**:按 head / 中间维切每一层,层内用 AllReduce 聚合(每 token `2·层数` 次)。
- **流水线并行 `--pp N`**:按层切成 N 段,相邻段间用 NCCL **P2P** 传 hidden state每 token 仅 `N-1` 次),
通信量远小于 AllReduce对无 NVLink 的 PCIe 更友好。
```bash
# 组内 GPU 0-34 卡张量并行 / 4 卡流水线并行
CUDA_VISIBLE_DEVICES=0,1,2,3 ./target/release/xserv-server /path/to/qwen3-8b --tp 4
CUDA_VISIBLE_DEVICES=0,1,2,3 ./target/release/xserv-server /path/to/qwen3-8b --pp 4
```
**PP 实测**dash5Qwen3-8B BF16单流贪心每卡显存为权重+最小 KV 池):
| 配置 | TTFT | TPOT | tok/s | 每卡显存 |
|------|------|------|-------|----------|
| 单卡 | 33ms | 17.4ms | 57.5 | 24.0 GB |
| PP=2 | 36ms | 18.1ms | 55.3 | 11.6 / 13.6 GB |
| PP=4 | 36ms | 17.9ms | 55.8 | 7.3 / 5.3 / 5.3 / 9.4 GB |
**质量对比**AIME 2025 30 题 + GSM8K 30 题贪心xserv 在 GPU 0-3、llama.cpp 在 GPU 4-7 并行):
| 引擎 | PP | AIME | GSM8K |
|------|----|------|-------|
| xserv | 1/2/4 | 8 / 7 / 7 (/30) | 29/30 (96.7%) 全部一致 |
| llama | 1/2/4 | 7 / 7 / 7 (/30) | 29/30 (96.7%) 全部一致 |
正确性hidden state 跨段是 **bit-exact BF16 P2P 拷贝**PP=4 输出与单卡逐字节一致用「单卡×2 vs
PP=4×2」对照确认——单卡自身因 cuBLAS 非确定性 run-to-run 会变,而 PP=4 可复现且落在某次单卡轨迹上)。
GSM8K 12 个格子全是 29/30xserv 与 llama.cpp 完全一致AIME 的 ±1 是长生成下贪心对 GEMM 抖动的敏感,
非 PP 或引擎效应。**收益在显存**(每卡权重+KV ≈ 1/Nv1 为串行流水线,单流 TPOT 基本持平、不优于单卡,
真正的吞吐提升需后续做 microbatch / 1F1B 重叠。完整数据见 `docs/benchmarks/pp-sweep.md`
## 路线图(节选)
已完成 Phase 018CUDA 基础设施 → Tensor → GEMM → Transformer kernels → Attention →
模型加载 → 分词器 → GPT-2 → KV cache → Qwen3-8B → Paged Attention → 连续批处理 →
HTTP API → Flash Attention 2 → 性能优化 → **张量并行TP****流水线并行PP**
并加入了 **llama.cpp 对比基准****KV CPU 换出** 等基础设施。
后续方向PP microbatch/1F1B 流水线重叠吞吐收益、2D TP×PP、投机解码、量化FP8 / INT8、多模态。
## 许可
MIT