1. 硬件环境
| 项目 |
规格 |
| GPU |
2 × NVIDIA GeForce RTX 2080 Ti(SM75 / Turing) |
| GPU 显存 |
22,528 MiB / 卡(共 ~44 GB) |
| GPU 驱动 |
580.159.03 |
| NVLink |
2 Link/GPU,双向 25.781 GB/s/Link(NV2) |
| GPU 最大时钟 |
GPU0: 2160 MHz / GPU1: 2175 MHz;显存: 7000 MHz |
| CPU |
AMD Ryzen 7 5700X 8 核 16 线程 |
| 内存 |
47 GiB DDR4 |
| 操作系统 |
Ubuntu 24.04.4 LTS(Kernel 6.17.0-29-generic) |
| CUDA Toolkit |
12.9 |
2. 软件环境
| 组件 |
版本 |
| Python |
3.12.3 |
| vLLM |
0.24.0 |
| PyTorch |
2.11.0 |
| FlashInfer |
0.6.12(flashinfer-python + flashinfer-cubin,含 PR3621 SM75 patch) |
| Triton |
3.6.0 |
| Transformers |
5.12.1 |
| NumPy |
2.3.5 |
vLLM 源码路径:/home/zyyuc/vllm-2080ti-0.24.0-qwopus
Python venv 路径:/home/zyyuc/vllm-env-0240-qwopus
FlashQLA 路径:/home/zyyuc/FlashQLA-SM70-SM75
3. 模型信息
| 项目 |
值 |
| 模型名称 |
Qwen3.6-27B-DSV4Pro-Thinking-FP8 |
| 模型路径 |
/home/zyyuc/models/Qwen3.6-27B-DSV4Pro-Thinking-FP8 |
| 服务名称 |
qwen-local |
| 架构 |
Qwen3_5ForConditionalGeneration |
| model_type |
qwen3_5 |
| Hidden layers |
64 |
| Hidden size |
5120 |
| Attention heads |
24 |
| KV heads |
4(GQA) |
| Vocab size |
248,320 |
| 最大位置编码 |
262,144 |
| 量化方式 |
FP8(Marlin weight-only,block_size=128×128) |
| 模型总大小 |
~29 GB(12 个语言模型 shard + 879 MB vision + 456 MB MTP) |
| 多模态 |
支持图片输入(Qwen3VL Processor,vision_config hidden_size=1152) |
| MTP |
支持(MTP3 投机解码,3 个 speculative tokens) |
混合架构说明
该模型为 Mamba + Attention 混合架构:
- Attention 层:使用 KV cache,O(n) 随上下文增长
- Mamba 层(linear_attn):固定递归状态,O(1) 不随上下文增长
- Mamba cache mode:
align(与 prefix caching 兼容)
4. 服务加载参数
4.1 systemd unit 完整配置
[Unit]
Description=Qwopus3.6 27B FP8 vLLM 0.24.0 stable server FP8 KV 100K
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=zyyuc
WorkingDirectory=/home/zyyuc/vllm-2080ti-0.24.0-qwopus
# ===== 环境变量 =====
Environment=CUDA_HOME=/usr/local/cuda
Environment=PATH=/usr/local/cuda/bin:/home/zyyuc/vllm-env-0240-qwopus/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/local/cuda/lib64/stubs
Environment=PYTHONPATH=/home/zyyuc/FlashQLA-SM70-SM75
Environment=HF_ENDPOINT=https://hf-mirror.com
Environment=VLLM_USE_DEEP_GEMM=0
Environment=OMP_NUM_THREADS=8
Environment=VLLM_USE_FLASHINFER_SAMPLER=0
Environment=VLLM_QWOPUS_MTP_BF16_DRAFT=1
Environment=VLLM_SM75_SPEC_SYNC_MODE=safe
# ===== 启动前校验 =====
ExecStartPre=/home/zyyuc/check-flashinfer-pr3621-sm75.sh
# ===== 启动命令 =====
ExecStart=/home/zyyuc/vllm-env-0240-qwopus/bin/python -m vllm.entrypoints.openai.api_server \
--host 0.0.0.0 \
--port 8000 \
--model /home/zyyuc/models/Qwen3.6-27B-DSV4Pro-Thinking-FP8 \
--served-model-name qwen-local \
--dtype half \
--tensor-parallel-size 2 \
--device-ids 0,1 \
--quantization fp8 \
--kv-cache-dtype fp8_e4m3 \
--max-model-len 100000 \
--enable-prefix-caching \
--max-num-seqs 1 \
--max-num-batched-tokens 4096 \
--enable-chunked-prefill \
--no-async-scheduling \
--skip-mm-profiling \
--reasoning-parser qwen3 \
--reasoning-config '{"reasoning_start_str":"<think>","reasoning_end_str":"</think>","default_thinking_token_budget":4000}' \
--default-chat-template-kwargs '{"enable_thinking":true}' \
--enable-auto-tool-choice \
--tool-call-parser qwen3_coder \
--chat-template-content-format string \
--gpu-memory-utilization 0.92 \
--additional-config '{"gdn_prefill_backend":"flashqla_legacy"}' \
--speculative-config '{"method":"mtp","num_speculative_tokens":3}' \
--compilation-config '{"cudagraph_mode":"PIECEWISE","cudagraph_capture_sizes":[4],"max_cudagraph_capture_size":4}' \
--override-generation-config '{"temperature":0.6,"top_p":0.95,"top_k":20,"min_p":0.0,"presence_penalty":0.0,"repetition_penalty":1.06}' \
--cpu-offload-gb 0 \
--disable-uvicorn-access-log
Restart=always
RestartSec=10
TimeoutStartSec=900
StandardOutput=append:/home/zyyuc/vllm-0240-main-8000.log
StandardError=append:/home/zyyuc/vllm-0240-main-8000.log
[Install]
WantedBy=multi-user.target
4.2 关键参数说明
| 参数 |
值 |
说明 |
--dtype half |
FP16 计算 |
SM75 无 BF16 Tensor Core,FP16 最快 |
--tensor-parallel-size 2 |
TP2 |
双卡并行,单卡 11GB 装不下 27B |
--device-ids 0,1 |
GPU 0+1 |
明确选卡,不设 CUDA_VISIBLE_DEVICES |
--quantization fp8 |
Marlin FP8 |
Weight-only 量化,节省显存 |
--kv-cache-dtype fp8_e4m3 |
FP8 KV Cache |
KV cache 容量 +79.5%(115K→207K tokens) |
--max-model-len 100000 |
100K 上下文 |
经 95K smoke 验证通过 |
--enable-prefix-caching |
开启 |
重复前缀加速,Mamba align 模式 |
--max-num-seqs 1 |
单请求 |
保证长上下文和显存稳定 |
--max-num-batched-tokens 4096 |
4K |
Chunked prefill 分块大小 |
--enable-chunked-prefill |
开启 |
长上下文必须,否则 prefill OOM |
--no-async-scheduling |
关闭 |
max_num_seqs=1 时无收益 |
--skip-mm-profiling |
跳过 |
不为多模态预留显存 profiling |
--reasoning-parser qwen3 |
Qwen3 thinking |
匹配 <think></think> 格式 |
--tool-call-parser qwen3_coder |
coder parser |
兼容 Claude 等客户端工具调用 |
--gpu-memory-utilization 0.92 |
92% |
留 8% 余量防止 OOM |
--additional-config gdn_prefill_backend=flashqla_legacy |
FlashQLA |
SM75 GDN prefill 必须用 legacy 后端 |
--speculative-config mtp,num_speculative_tokens=3 |
MTP3 |
投机解码,3 个 draft tokens |
--compilation-config cudagraph_capture_sizes=[4] |
仅 size 4 |
max_num_seqs=1 + MTP3 = 4 token slots |
--override-generation-config |
采样参数 |
temperature=0.6, top_p=0.95, top_k=20, repetition_penalty=1.06 |
4.3 环境变量说明
| 环境变量 |
值 |
说明 |
VLLM_USE_DEEP_GEMM=0 |
关闭 |
SM75 不支持 DeepGEMM |
VLLM_USE_FLASHINFER_SAMPLER=0 |
关闭 |
SM75 上 FlashInfer sampler 有 bug |
VLLM_QWOPUS_MTP_BF16_DRAFT=1 |
BF16 draft |
MTP draft 模型用 BF16 精度 |
VLLM_SM75_SPEC_SYNC_MODE=safe |
safe 模式 |
SM75 投机解码安全同步 |
OMP_NUM_THREADS=8 |
8 线程 |
CPU 端 tokenizer 并行 |
PYTHONPATH=.../FlashQLA-SM70-SM75 |
FlashQLA |
SM75 GDN kernel 路径 |
HF_ENDPOINT=hf-mirror.com |
镜像 |
国内 HuggingFace 镜像 |
5. 运行时状态
5.1 KV Cache 配置
| 指标 |
值 |
| cache_dtype |
fp8_e4m3 |
| block_size |
1600(自动对齐) |
| num_gpu_blocks |
162 |
| kv_cache_size_tokens |
207,692 |
| kv_cache_max_concurrency |
2.077 |
| mamba_cache_mode |
align |
| mamba_ssm_cache_dtype |
float32 |
| enable_prefix_caching |
True |
5.2 GPU 显存占用
| GPU |
已用 |
总量 |
利用率 |
| GPU0 |
21,720 MiB |
22,528 MiB |
96.4% |
| GPU1 |
21,752 MiB |
22,528 MiB |
96.5% |
5.3 显存分配估算
模型权重 (27B FP8 / TP2): ~19,500 MiB/卡 (固定不可变)
CUDA context + PyTorch: ~1,700 MiB/卡 (固定开销)
KV cache (162 blocks): ~507 MiB/卡 (很小)
剩余空闲: ~280 MiB/卡
6. 性能测试结果
6.1 测试方法
- 测试脚本:
/home/zyyuc/fp8_vs_fp16_ab_test.py
- 每个 prompt 使用 64 字符随机 UUID + 随机词库生成,确保
prompt_tokens_cached=0
- JIT 暖机:短请求 ×2 + 20K 暖机 + 60K 暖机
- 正式测试:20K ×3(max_tokens=256)+ 60K ×2(max_tokens=128)
- 流式请求,记录 TTFT、decode tok/s、prefill tok/s、MTP acceptance
6.2 FP8 KV Cache 测试结果(当前生产配置)
| Run |
上下文 |
TTFT (s) |
Prefill (tok/s) |
Decode (tok/s) |
MTP Acceptance |
| run1 |
17,042 tok |
13.090 |
1,301.9 |
88.0 |
78.9% |
| run2 |
17,052 tok |
13.138 |
1,297.9 |
77.6 ️ |
68.3% |
| run3 |
17,041 tok |
13.182 |
1,292.7 |
87.8 |
78.9% |
| run1 |
50,983 tok |
45.587 |
1,118.4 |
87.1 |
63.6% |
| run2 |
51,109 tok |
46.039 |
1,110.1 |
105.6 |
76.1% |
️ run2 受 Triton JIT 编译干扰,decode 偏低
6.3 FP16 KV Cache 基线对比
| Run |
上下文 |
TTFT (s) |
Prefill (tok/s) |
Decode (tok/s) |
MTP Acceptance |
| run1 |
17,131 tok |
13.180 |
1,299.8 |
87.0 |
77.5% |
| run2 |
17,129 tok |
13.236 |
1,294.1 |
87.0 |
77.1% |
| run3 |
17,054 tok |
13.162 |
1,295.7 |
81.5 |
71.6% |
| run1 |
51,036 tok |
45.733 |
1,116.0 |
117.7 |
81.1% |
| run2 |
51,036 tok |
46.042 |
1,108.5 |
94.9 |
68.3% |
6.4 汇总对比
| 指标 |
FP16 均值 |
FP8 均值 |
差异 |
结论 |
| 20K TTFT |
13.193s |
13.137s |
-0.4% |
持平 |
| 20K Prefill |
1,296.5 tok/s |
1,297.5 tok/s |
+0.1% |
持平 |
| 20K Decode |
85.2 tok/s |
84.5 tok/s |
-0.8% |
持平 |
| 20K MTP |
75.4% |
75.4% |
0% |
持平 |
| 60K TTFT |
45.888s |
45.813s |
-0.2% |
持平 |
| 60K Prefill |
1,112.3 tok/s |
1,114.2 tok/s |
+0.2% |
持平 |
| 60K Decode |
106.3 tok/s |
96.3 tok/s |
-9.4% |
持平* |
| 60K MTP |
74.7% |
69.8% |
-4.9pp |
持平* |
| KV cache 容量 |
115,714 tok |
207,692 tok |
+79.5% |
FP8 优势 |
*60K 仅 2 次采样,方差大,不具统计显著性
6.5 关键结论
- FP8 KV Cache 不带来 decode/prefill 性能提升:与 FP16 基本持平,符合 SM75 架构预期(无原生 FP8 Tensor Core,KV 需反量化为 FP16 计算)
- FP8 KV Cache 的唯一真实收益是容量 +79.5%:从 115K tokens 提升到 207K tokens
- 性能瓶颈是 GPU 计算饱和:SM 利用率 96-100%,功耗接近 200W 限制
- MTP3 投机解码有效:acceptance ~75%,decode 速度显著高于无投机解码(~85 vs ~29 tok/s)
