Qwen3.8-27B 开源后,我用双 RTX 4090 跑通了:vLLM 0.27.1、128K 上下文与 MTP 实测

0 阅读10分钟

Qwen3.8-27B 开源后,我用双 RTX 4090 跑通了:vLLM 0.27.1、128K 上下文与 MTP 实测

Qwen3.8-27B-FP8 ModelScope 官方封面.png Qwen3.8-27B 发布后,我第一时间在现有双 GPU 服务器上重新搭了一套独立环境。

这次没有沿用旧模型的 Python 环境,也没有只记录一条“能启动”的命令。我把模型下载、CUDA 版本、vLLM、systemd、API 鉴权、128K 长上下文和 MTP 都实际走了一遍。

最终结果如下:

  • 官方 FP8 权重分片约 29GB,ModelScope 完整仓库页显示约 30.89GB。
  • vLLM 0.27.1PyTorch 2.13.0+cu130 和双 GPU 张量并行启动成功。
  • 服务由 systemd 托管,对外提供带 API Key 的 OpenAI 兼容接口。
  • 服务上下文配置为 128K,2K/512 的 4 并发压测 100 次全部成功。
  • 近 128K 的单并发和 4 并发压测均完成,没有请求失败。
  • Prefix Cache 和 MTP 都做了独立对照;MTP 有明显提升,但暂时保留为实验配置。

本文所有用户名、IP 和密钥都使用 <USER><SERVER_IP><API_KEY> 占位符。执行前必须替换为自己的值。

1. 先看模型:27B Dense、原生视觉与 256K 上下文

Qwen3.8-27B-FP8 官方模型页给出的核心信息是:

  • 模型类型:带视觉编码器的因果语言模型。
  • 语言模型参数量:27B Dense。
  • 隐藏维度:5120。
  • 网络层数:64。
  • 混合结构:16 × (3 × (Gated DeltaNet → FFN) → 1 × (Gated Attention → FFN))
  • MTP:经过多步训练。
  • 原生上下文:262,144 Token,可通过额外扩展配置支持更长上下文。
  • FP8:细粒度块量化,block size 为 128。
  • 多模态:原生支持图片和视频理解。

image.png

图 1:ModelScope 官方模型页的模型概览。这里的 262,144 是模型原生上限,不是部署后自动获得的服务长度。

官方 Benchmark 应该怎么看

ModelScope 模型页同时给出了 Text 和 VL 两组官方结果。

image.png

图 2:ModelScope 官方 Text Benchmark。数据来自官方评测 Harness。

image.png

图 3:ModelScope 官方 VL Benchmark。

选几个容易理解的官方指标:

BenchmarkQwen3.8-27BQwen3.6-27BQwen3.7-PlusOpus4.6 Max
SWE-bench Pro61.753.557.653.4
CoWorkBench70.761.065.168.2
LiveCodeBench v690.383.989.688.8
OSWorld-Verified84.363.973.372.7
AndroidWorld81.970.381.062.0

2. 服务器与软件版本矩阵

本文实际跑通的版本如下:

组件实测版本
Linux Kernel7.0.0-28-generic
NVIDIA Driver595.84
GPU2 张 RTX 4090,各个约 48GiB
Python3.12
uv0.12.5
modelscope-hub0.2.0
PyTorch2.13.0+cu130
torchvision0.28.0+cu130
torchaudio2.11.0+cu130
Transformers5.15.0
vLLM0.27.1
CUDA Runtime13.0

注意:modelscope-hub 0.2.0 它提供的命令是 ms-hub,本文统一使用这个 CLI。 如果安装的版本是在<=0.1.8 在 PyPI 中注册的命令是 ms 和 modelscope

宿主机基线:

 # 核对内核、驱动、GPU、磁盘和共享内存
 uname -r
 nvidia-smi
 df -h /data
 df -h /dev/shm

0-第一个环境配置.png

3. 从空目录开始搭建独立环境

我给 Qwen3.8 单独建立项目、模型、缓存和压测目录。

3.1 创建目录

 # 将 <USER> 替换为实际 Linux 用户名
 sudo mkdir -p /home/<USER>/projects/vllm-qwen38
 sudo mkdir -p /data/models/hf
 sudo mkdir -p /data/cache/qwen38/modelscope-hub
 sudo mkdir -p /data/cache/qwen38/huggingface
 sudo mkdir -p /data/cache/qwen38/torchinductor
 sudo mkdir -p /data/cache/qwen38/vllm
 sudo mkdir -p /data/artifacts/qwen38
 ​
 sudo chown -R <USER>:<USER> /home/<USER>/projects/vllm-qwen38
 sudo chown -R <USER>:<USER> /data/models/hf
 sudo chown -R <USER>:<USER> /data/cache/qwen38
 sudo chown -R <USER>:<USER> /data/artifacts/qwen38

最终目录关系是:

 /home/<USER>/projects/vllm-qwen38/            项目、虚拟环境和启动脚本
 /home/<USER>/projects/vllm-qwen38/.env        模型路径与内部 API Key
 /data/models/hf/Qwen3.8-27B-FP8/             模型目录
 /data/cache/qwen38/                           ModelScope、HF、vLLM、编译缓存
 /data/artifacts/qwen38/                       环境记录和压测结果
 /etc/systemd/system/qwen38-main.service       systemd 服务

①创建接收的目录文件.png

3.2 更新 uv,创建 Python 3.12 环境

 # 更新 uv 并创建 Qwen3.8 独立虚拟环境
 uv self update
 uv --version
 ​
 cd /home/<USER>/projects/vllm-qwen38
 uv venv --python 3.12 --seed --managed-python .venv
 source .venv/bin/activate
 python --version

3.3 安装 modelscope-hub 0.2.0

 # 下载工具不需要 CUDA 版 PyTorch,先按 CPU 后端安装
 UV_TORCH_BACKEND=cpu uv pip install \
   --python .venv/bin/python \
   'modelscope-hub==0.2.0'
 ​
 ms-hub --version
 python -c "from importlib.metadata import version; print(version('modelscope-hub'))"
 uv pip check

③安装modelscope 0.20版本并进行校验.png

4. 用 ModelScope 一条命令下载完整模型

指定最终目录即可直接下载:

 cd /home/<USER>/projects/vllm-qwen38
 source .venv/bin/activate
 ​
 # 使用 ModelScope 国内站,完整仓库直接写入最终模型目录
 export MODELSCOPE_ENDPOINT=https://modelscope.cn
 export MODELSCOPE_CACHE=/data/cache/qwen38/modelscope-hub
 export MODELSCOPE_DOWNLOAD_PARALLEL_WORKERS=4
 export MODELSCOPE_DOWNLOAD_MAX_RETRIES=10
 export MODEL_DIR=/data/models/hf/Qwen3.8-27B-FP8
 ​
 mkdir -p "$MODEL_DIR"
 ​
 ms-hub download Qwen/Qwen3.8-27B-FP8 \
   --local-dir "$MODEL_DIR" \
   --max-workers 8

下载中断后,重新执行同一条 ms-hub download 即可续传。如果需要严格复现,额外增加 --revision <MODEL_REVISION> 固定官方 revision。

④安装下载ms中的qwen3.8 27b模型.png

下载完成后检查配置、索引和权重:

 # 核对模型配置、权重索引、权重分片和总大小
 test -s "$MODEL_DIR/config.json"
 test -s "$MODEL_DIR/model.safetensors.index.json"
 find "$MODEL_DIR" -maxdepth 1 -name '*.safetensors' -type f | sort | head
 du -sh "$MODEL_DIR"
 ​
 python - "$MODEL_DIR" <<'PY'
 import json
 from pathlib import Path
 import sys
 ​
 model_dir = Path(sys.argv[1])
 config = json.load(open(model_dir / "config.json"))
 text = config.get("text_config", config)
 ​
 print("architectures:", config.get("architectures"))
 print("max_position_embeddings:", text.get("max_position_embeddings"))
 print("vision:", bool(config.get("vision_config")))
 print("quantization:", bool(
     text.get("quantization_config") or config.get("quantization_config")
 ))
 ​
 assert "Qwen3_5ForConditionalGeneration" in config.get("architectures", [])
 assert text.get("max_position_embeddings") == 262144
 assert config.get("vision_config")
 assert text.get("quantization_config") or config.get("quantization_config")
 PY

⑤校验qwen3.827B下载成功.png

5. 安装 vLLM 0.27.1 与 cu130 兼容栈

这套环境的原则很简单:让 vLLM 决定其锁定的 PyTorch 版本,不再单独升级 torchtorchvisiontorchaudio

 cd /home/<USER>/projects/vllm-qwen38
 source .venv/bin/activate
 ​
 # 使用 cu130 后端安装固定版本,避免 CUDA wheel 混装
 uv pip install \
   --python .venv/bin/python \
   --torch-backend=cu130 \
   'vllm==0.27.1' \
   'transformers==5.15.0' \
   'packaging>=25.0'
 ​
 uv pip check

⑥安装下载vllm环境.png

随后做强制断言:

 python - <<'PY'
 from importlib.metadata import version
 ​
 expected = {
     "vllm": "0.27.1",
     "torch": "2.13.0",
     "torchvision": "0.28.0",
     "torchaudio": "2.11.0",
     "transformers": "5.15.0",
 }
 ​
 for package, wanted in expected.items():
     actual = version(package)
     print(f"{package}: {actual}")
     assert actual == wanted, f"{package}: expected {wanted}, got {actual}"
 PY
 ​
 python - <<'PY'
 import torch
 import vllm
 import vllm._C_stable_libtorch as vllm_native
 from vllm.platforms import current_platform
 ​
 print("vLLM:", vllm.__version__)
 print("PyTorch:", torch.__version__)
 print("CUDA Runtime:", torch.version.cuda)
 print("GPU count:", torch.cuda.device_count())
 print("vLLM platform:", current_platform.device_type)
 print("native extension:", vllm_native.__file__)
 ​
 assert vllm.__version__ == "0.27.1"
 assert torch.version.cuda == "13.0"
 assert torch.cuda.is_available()
 assert torch.cuda.device_count() == 2
 assert current_platform.is_cuda()
 PY

vLLM 0.27.1 已经使用 _C_stable_libtorch。而不是以前的的 import vllm._C 可能直接报模块不存在,不能据此判断 CUDA 安装失败。

⑦安装vllm0.27.1版本成功.png

6. 最终启动配置:128K、TP=2、图片和视频 <未启用 Prefix Cache 跟 MTP>

6.1 .env 与 API Key

先生成密钥:

 openssl rand -hex 32

然后在项目目录创建 .env

 cd /home/<USER>/projects/vllm-qwen38
 install -m 600 /dev/null .env
 ​
 cat > .env <<'EOF'
 MODEL_DIR=/data/models/hf/Qwen3.8-27B-FP8
 VLLM_INTERNAL_API_KEY=<API_KEY>
 CUDA_VISIBLE_DEVICES=0,1
 HF_HOME=/data/cache/qwen38/huggingface
 HF_HUB_CACHE=/data/cache/qwen38/huggingface/hub
 TORCHINDUCTOR_CACHE_DIR=/data/cache/qwen38/torchinductor
 VLLM_CACHE_ROOT=/data/cache/qwen38/vllm
 PYTHONUNBUFFERED=1
 EOF
 ​
 chmod 600 .env
 grep -qxF '.env' .gitignore 2>/dev/null || echo '.env' >> .gitignore

VLLM_INTERNAL_API_KEY 是部署侧私有变量。启动脚本会把它映射为 vLLM 识别的 VLLM_API_KEY,然后取消导出私有变量。这样既不会把 Key 放进命令行,也不会触发 vLLM 对未知 VLLM_* 环境变量的检查。

⑧配置.env文件环境变量 api-key跟model路径等.png

⑧-1 env文件内容.png

6.2 完整启动脚本

文件路径:

 /home/<USER>/projects/vllm-qwen38/start-qwen38-main.sh

完整内容:

 #!/usr/bin/env bash
 set -euo pipefail
 ​
 PROJECT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
 ENV_FILE="$PROJECT_DIR/.env"
 export PATH="$PROJECT_DIR/.venv/bin:$PATH"
 ​
 if [[ ! -r "$ENV_FILE" ]]; then
   echo "Missing or unreadable environment file: $ENV_FILE" >&2
   exit 1
 fi
 ​
 set -a
 source "$ENV_FILE"
 set +a
 ​
 : "${MODEL_DIR:?MODEL_DIR is required}"
 : "${VLLM_INTERNAL_API_KEY:?VLLM_INTERNAL_API_KEY is required}"
 export VLLM_API_KEY="$VLLM_INTERNAL_API_KEY"
 unset VLLM_INTERNAL_API_KEY
 ​
 cd "$PROJECT_DIR"
 ​
 exec "$PROJECT_DIR/.venv/bin/vllm" serve "$MODEL_DIR" \
   --host 0.0.0.0 \
   --port 9999 \
   --served-model-name qwen3.8-27b-fp8 qwen-27b-prod \
   --tensor-parallel-size 2 \
   --max-model-len 131072 \
   --gpu-memory-utilization 0.90 \
   --max-num-seqs 4 \
   --max-num-batched-tokens 8192 \
   --enable-chunked-prefill \
   --kv-cache-dtype fp8 \
   --reasoning-parser qwen3 \
   --enable-auto-tool-choice \
   --tool-call-parser qwen3_coder \
   --mm-encoder-tp-mode data \
   --mm-processor-cache-type shm \
   --limit-mm-per-prompt '{"image":10,"video":{"count":1,"num_frames":32}}' \
   --media-io-kwargs '{"video":{"num_frames":32}}' \
   --disable-custom-all-reduce

落盘后检查 Shell 语法:

 cd /home/<USER>/projects/vllm-qwen38
 chmod 750 start-qwen38-main.sh
 bash -n start-qwen38-main.sh

⑨ 启动脚本内容.png

6.3 这些参数解决什么问题

参数当前值含义
--tensor-parallel-size2权重和计算切到两张 GPU;它不是并发数。
--max-model-len131072服务输入与输出总长度上限 128K。
--gpu-memory-utilization0.90每个 Worker 的目标显存占用比例,仍保留约 10% 余量。
--max-num-seqs4调度器同时处理的活跃序列上限,不是 HTTP 连接上限。
--max-num-batched-tokens8192单轮调度 Token 预算。
--enable-chunked-prefill开启长 Prompt 分块预填充,避免单个长请求长期独占调度器。
--kv-cache-dtypefp8KV Cache 使用 FP8,降低长上下文缓存显存;不等同于权重 FP8。
--reasoning-parserqwen3把 reasoning 与最终 content 分离。
--enable-auto-tool-choice开启允许 tool_choice=auto
--tool-call-parserqwen3_coder解析 OpenAI 兼容 tool_calls;Agent 上线前仍需专项验证。
--mm-encoder-tp-modedata多模态编码器按数据维度使用 TP Worker。
--mm-processor-cache-typeshm多进程通过共享内存复用媒体预处理结果。
--limit-mm-per-prompt10 图、1 视频、32 帧服务侧许可上限,不代表已经完成极限稳定性验证。
--disable-custom-all-reduce开启不依赖当前双卡 P2P,自定义 all-reduce 回退到 NCCL。

权重 FP8 由模型 config.json 自动识别,所以没有手工添加 --quantization fp8

图片最多 10 张是这套服务的部署限额,不是 Qwen 官方宣称的固定硬上限。视频限制为每请求 1 个、最多 32 帧,也是为了控制上下文和显存峰值。

7. systemd 托管与启动

创建 /etc/systemd/system/qwen38-main.service

 [Unit]
 Description=Qwen3.8 27B FP8 vLLM Service
 Wants=network-online.target
 After=network-online.target
 ​
 [Service]
 Type=simple
 User=<USER>
 Group=<USER>
 WorkingDirectory=/home/<USER>/projects/vllm-qwen38
 ExecStart=/home/<USER>/projects/vllm-qwen38/start-qwen38-main.sh
 Restart=on-failure
 RestartSec=10
 TimeoutStartSec=900
 TimeoutStopSec=120
 KillMode=mixed
 LimitNOFILE=1048576
 TasksMax=infinity
 ​
 [Install]
 WantedBy=multi-user.target

加载并启动:

 # 重新加载 unit,设置开机自启并跟踪启动日志
 sudo systemctl daemon-reload
 sudo systemctl enable --now qwen38-main
 sudo systemctl status qwen38-main --no-pager
 journalctl -u qwen38-main -f

启动成功至少要看到:

 Application startup complete
 Starting vLLM server on http://0.0.0.0:9999

⑩ 配置systemctl 服务内容.png

⑩-1 systemctl service文件内容.png

8. API 验收:鉴权、模型列表和文本请求

8.1 健康与鉴权

 cd /home/<USER>/projects/vllm-qwen38
 set -a
 source .env
 set +a
 ​
 curl -i http://127.0.0.1:9999/health \
   -H "Authorization: Bearer $VLLM_INTERNAL_API_KEY"
 ​
 curl http://127.0.0.1:9999/v1/models \
   -H "Authorization: Bearer $VLLM_INTERNAL_API_KEY"
 ​
 # 不带 Key 的模型请求应返回 401
 curl -i http://127.0.0.1:9999/v1/models

模型列表应包含两个 served name:

 qwen3.8-27b-fp8
 qwen-27b-prod

8.2 文本请求

 curl http://127.0.0.1:9999/v1/chat/completions \
   -H "Authorization: Bearer $VLLM_INTERNAL_API_KEY" \
   -H "Content-Type: application/json" \
   -d '{
     "model": "qwen3.8-27b-fp8",
     "messages": [
       {"role": "user", "content": "请只回复:Qwen3.8 服务正常。"}
     ],
     "max_tokens": 64,
     "temperature": 0.7,
     "top_p": 0.8,
     "top_k": 20,
     "presence_penalty": 1.5,
     "chat_template_kwargs": {
       "enable_thinking": false
     }
   }'

11 成功验证访问.png

8.3 图片和视频请求

拿电脑的ClaudeCode插件去测试了图片一下

image.png

9. 2K 基线与近 128K 压测

为了观察纯服务性能,我的压测统一关闭 thinking。这样输出长度更可控,也更适合比较 Prefix Cache 与 MTP。

9.1 2K 输入、512 输出、4 并发

 cd /home/<USER>/projects/vllm-qwen38
 source .venv/bin/activate
 ​
 export HF_HUB_OFFLINE=1
 export TRANSFORMERS_OFFLINE=1
 set -a
 source .env
 set +a
 ​
 vllm bench serve \
   --backend openai-chat \
   --base-url http://127.0.0.1:9999 \
   --endpoint /v1/chat/completions \
   --model /data/models/hf/Qwen3.8-27B-FP8 \
   --tokenizer /data/models/hf/Qwen3.8-27B-FP8 \
   --served-model-name qwen3.8-27b-fp8 \
   --dataset-name random \
   --random-input-len 2048 \
   --random-output-len 512 \
   --num-prompts 100 \
   --request-rate 4 \
   --max-concurrency 4 \
   --header "Authorization=Bearer $VLLM_INTERNAL_API_KEY" \
   --extra-body '{"chat_template_kwargs":{"enable_thinking":false}}' \
   --save-result \
   --result-dir /data/artifacts/qwen38

12-1 进行离线4并发压测结果.png

9.2 近 128K 单并发

输入使用 126,976 Token,输出使用 2,048 Token,总计 129,024,为聊天模板保留约 2,048 Token 余量。

 cd /home/<USER>/projects/vllm-qwen38
 source .venv/bin/activate
 ​
 export HF_HUB_OFFLINE=1
 export TRANSFORMERS_OFFLINE=1
 set -a
 source .env
 set +a
 ​
 vllm bench serve \
   --backend openai-chat \
   --base-url http://127.0.0.1:9999 \
   --endpoint /v1/chat/completions \
   --model /data/models/hf/Qwen3.8-27B-FP8 \
   --tokenizer /data/models/hf/Qwen3.8-27B-FP8 \
   --served-model-name qwen3.8-27b-fp8 \
   --dataset-name random \
   --random-input-len 126976 \
   --random-output-len 2048 \
   --num-prompts 1 \
   --request-rate 1 \
   --max-concurrency 1 \
   --ignore-eos \
   --header "Authorization=Bearer $VLLM_INTERNAL_API_KEY" \
   --extra-body '{"chat_template_kwargs":{"enable_thinking":false}}' \
   --save-result \
   --result-dir /data/artifacts/qwen38 \
   --result-filename qwen38-near-128k-single.json

12-4 进行离线单并发压测 130K上下文压测结果.png

9.3 近 128K 四并发

只有单并发通过后再运行:

 cd /home/<USER>/projects/vllm-qwen38
 source .venv/bin/activate
 ​
 export HF_HUB_OFFLINE=1
 export TRANSFORMERS_OFFLINE=1
 set -a
 source .env
 set +a
 ​
 vllm bench serve \
   --backend openai-chat \
   --base-url http://127.0.0.1:9999 \
   --endpoint /v1/chat/completions \
   --model /data/models/hf/Qwen3.8-27B-FP8 \
   --tokenizer /data/models/hf/Qwen3.8-27B-FP8 \
   --served-model-name qwen3.8-27b-fp8 \
   --dataset-name random \
   --random-input-len 126976 \
   --random-output-len 2048 \
   --num-prompts 4 \
   --request-rate inf \
   --max-concurrency 4 \
   --ignore-eos \
   --header "Authorization=Bearer $VLLM_INTERNAL_API_KEY" \
   --extra-body '{"chat_template_kwargs":{"enable_thinking":false}}' \
   --save-result \
   --result-dir /data/artifacts/qwen38 \
   --result-filename qwen38-near-128k-concurrency4.json

12-6 进行离线4并发压测 130K上下文压测结果.png

9.4 实测汇总

场景成功/失败Output tok/sMean TTFTMean TPOT
2K/512,4 并发基线100/0133.061080.70 ms27.95 ms
126976/2048,单并发1/018.5542252.54 ms32.80 ms
126976/2048,4 并发4/034.29105883.49 ms64.61 ms

长上下文结果很直观:4 个请求都能完成,但 TTFT 和 TPOT 都显著上升。

近 128K 四并发期间,两张 GPU 均达到 100% 利用率,显存约为 43.2/48.0GiB 和 42.9/48.0GiB。

10. Prefix Cache 与 MTP:分别测试,再考虑组合

10.1 Prefix Cache

在稳定脚本中增加:

   --enable-prefix-caching \

然后重启并核对日志:

 sudo systemctl restart qwen38-main
 journalctl -u qwen38-main -b --no-pager | \
   grep -Ei 'prefix|cache|Application startup complete'

启用prefix日志验证.png

相同 2K/512 随机数据的结果是:

配置成功/失败Output tok/sMean TTFTMean TPOT
无 Prefix Cache100/0133.061080.70 ms27.95 ms
开启 Prefix Cache100/0132.741087.93 ms28.01 ms

13-1 进行离线4并发压测结果.png

这并不代表 Prefix Cache 无效。random 数据集几乎没有重复长前缀,自然无法体现缓存命中收益。

10.2 Prefix Cache + MTP=1/2/3 组合实验

三轮 MTP 实机截图对应的是 Prefix Cache 保持开启 时的组合实验,而不是单独 MTP。因此,下面的性能差值不能全部归因于 MTP。

启动脚本同时增加两行:

   --enable-prefix-caching \
   --speculative-config '{"method":"mtp","num_speculative_tokens":2}' \

2 分别改成 123,每轮都重启服务、确认 MTP 配置已加载,再运行完全相同的 2K/512 压测。

日志检查:

 sudo systemctl restart qwen38-main
 journalctl -u qwen38-main -b --no-pager | \
   grep -Ei 'speculative|mtp|num_speculative_tokens|Application startup complete'

实验结果:

配置成功/失败Output tok/sMean TTFTMean TPOT接受率
普通解码基线100/0133.061080.70 ms27.95 ms不适用
Prefix + MTP=1100/0145.91177.61 ms27.05 ms本轮未记录
Prefix + MTP=2100/0184.94598.32 ms20.17 ms65.73%
Prefix + MTP=3100/0194.79637.98 ms19.05 ms52.62%

Prefix + MTP=1 14 4并发测试 启动 prefix mpt=1.png

Prefix + MTP=2 14 4并发测试 启动 prefix mpt=2 案例2.png

Prefix + MTP=3 14 4并发测试 启动 prefix mpt=3 案例2.png

这组数据粗略说明 speculative decoding 在当前环境中确实运行过,也说明 num_speculative_tokens 不是越大接受率就越高。

11. 遇到的几个问题

现象原因处理
No such file or directory: 'ninja'FlashInfer JIT 需要 ninja,systemd PATH 中找不到安装 ninja-build,并保留脚本中的 .venv/bin PATH
Using default W8A8 Block FP8 kernel config没有匹配当前 GPU 与矩阵形状的预调优配置这是性能警告,不是启动失败

缺少 ninja 时可执行:

 sudo apt update
 sudo apt install -y ninja-build
 ​
 which ninja
 ninja --version
 sudo systemctl restart qwen38-main

12. 最终结论

Qwen3.8-27B-FP8 在这套双 GPU 环境中已经完成了从下载到 API、从 2K 到近 128K、从普通解码到 MTP 的完整部署链路。

我最终保留的生产基线是:

  • vLLM 0.27.1 与 cu130 固定版本环境。
  • TP=2、128K、4 活跃序列、FP8 KV Cache、Chunked Prefill。
  • systemd 托管、API Key 鉴权和稳定 served alias。
  • 默认不启用 MTP。
  • 开启 Prefix Cache 重复前缀业务。

最值得保留的经验并不是某个吞吐数字,而是把稳定基线和实验参数分开。只要目录、环境、脚本、服务和压测结果都能独立回退,后续升级 vLLM、扩大上下文或继续调 MTP,就不会把已经可用的服务一起破坏。

官方参考