VLLM部署Qwen3-30B-A3B-Instruct-2507-FP8以及GLM-5

38 阅读8分钟

VLLM部署Qwen3-30B-A3B-Instruct-2507-FP8以及GLM-5

背景信息:使用VLLM降低首Token和后续Token生成所需时间,现有两张24G4090GPU

0. GLM-5

GLM-5 全新基座为从“写代码”到“写工程”的能力演进提供了坚实基础:

  • 参数规模扩展:从 355B(激活 32B)扩展至 744B(激活 40B),预训练数据从 23T 提升至 28.5T,更大规模的预训练算力显著提升了模型的通用智能水平
  • 异步强化学习:构建全新的 “Slime” 框架,支持更大模型规模及更复杂的强化学习任务,提升强化学习后训练流程效率;提出异步智能体强化学习算法,使模型能够持续从长程交互中学习,充分激发预训练模型的潜力
  • 稀疏注意力机制:首次集成 DeepSeek Sparse Attention,在维持长文本效果无损的同时,大幅降低模型部署成本,提升 Token Efficiency

GLM-5 技术报告全解读——a16z:“最好的开源模型” | 人人都是产品经理

1. Qwen3-30B-A3B-Instruct-2507-FP8模型释义

  1. 该模型是MoE架构,FP8也就是8位浮点数精度;
  2. A3B表示Active 3 Billion,这表示:
    1. 虽然它总参数有30B,但每次处理一个字的时候,只有3B参数在干活,
    2. 它拥有30B模型的博学知识,但推理速度却接近3B模型的轻快,
    3. 4090显卡原生支持FP8加速,相比于BF16,FP8显存占用减半,计算速度翻倍,并且几乎不损失精度。

2. Docker部署前的检查

  1. 显卡驱动检查nvidia-smi
    1. 驱动版本Driver Version必须在535.104+,因为FP8精度和最新的vLLM算子需要此配置支持
  2. PCle带宽检查nvidia-smi -q -d UTILIZATION
    1. 看一下Max Link Speed 和 Current Link Speed。4090在做张量并行TP的时候,两张卡要频繁交换数据,如果主板把第二个插槽的速度降到了PCle 3.0 x4,那速度就会比预期的降低一半,确保是Gen4x16或者x8.
  3. 内存和Swap
    1. 虽然模型在显存里面,但加载模型的瞬间需要大量的内存RAM。对于30B的模型,建议内存至少64GB,否则加载的时候可能OOM

3. Dokcer 环境

3.1 Qwen

vLLm有很多复杂的CUDA算子,不同版本的PyTorch和CUDA组合极易报错

  1. Dockerfile或者直接拉取官方镜像

    docker pull vllm/vllm-openai:xxxx,指定版本,不要用latest
    
  2. 启动脚本

    #!/bin/bash
    
    # 定义路径,改造成你自己的路径
    MODEL_PATH="/data/models/Qwen3-30B-A3B-Instruct-2507-FP8"
    CONTAINER_NAME="vllm-qwen-prod"
    
    docker run -d --gpus all \
        --name $CONTAINER_NAME \
        --shm-size=16gb \
        --ipc=host \
        -p 8000:8000 \
        -v $MODEL_PATH:/model \
        --restart unless-stopped \
        vllm/vllm-openai:v0.7.0 \
        --model /model \
        --tensor-parallel-size 2 \
        --max-model-len 16384 \
        --gpu-memory-utilization 0.90 \
        --trust-remote-code \
        --dtype fp8 \
        --kv-cache-dtype fp8 \
        --served-model-name qwen-30b
    
    • --shm-size=16gb:Docker的共享内存,多卡并行NCCL通讯时需要,默认的64MB会直接导致死机
    • --tensor-parallel-size:2:把30B的矩阵切开,分布到两张卡上
    • --max-model-len:16384:4090显存只有24GB,如果不限制长度,vLLM会默认尝试申请巨大的显存空间。如果不需要超长对话,设置成16K或者8K可以显著增加吞吐量
    • --kv-cache-dtype:fp8:现在用的模型就是FP8模型,把KV缓存也设置位FP8,可以多一倍的对话内容。
    • --gpu-memory-utilization:0.90:预留10%的显存给显卡驱动和系统,防止爆显存。

3.2 GLM-5

由于 GLM-5 需要最新版 transformers 支持,官方镜像暂未包含,需要构建自定义镜像。

创建 Dockerfile

FROM vllm/vllm-openai:v0.17.1-cu130

# 安装 git 用于从源码安装 transformers
RUN apt-get update && apt-get install -y git && \
    rm -rf /var/lib/apt/lists/*

# 安装最新版 transformers(GLM-5 需要)
RUN pip install --no-cache-dir git+https://github.com/huggingface/transformers.git

WORKDIR /app

ENTRYPOINT ["vllm"]

构建镜像:

docker build -t vllm/vllm-openai:glm5 .

已推送到公共仓库:lixd96/vllm-openai:v0.17.1-cu130,可直接拉取使用

docker run -d \
  --name vllm-glm5 \
  --runtime nvidia \
  --gpus '"device=0,1,2,3"' \
  -p 8000:8000 \
  -v /raid/lixd/models/glm5-int4-mixed-autoround:/app/model \
  --shm-size 16g \
  vllm/vllm-openai:glm5 \
  serve /app/model \
    --tensor-parallel-size 4 \
    --tool-call-parser glm47 \
    --reasoning-parser glm45 \
    --enable-auto-tool-choice \
    --served-model-name glm5 \
    --trust-remote-code \
    --gpu-memory-utilization 0.85 \
    --host 0.0.0.0 \
    --port 8000

关键参数说明:

参数说明
--tensor-parallel-size张量并行数,通常等于 GPU 数量
--tool-call-parser glm47使用 GLM 系列工具调用解析器
--reasoning-parser glm45启用 GLM 推理能力
--enable-auto-tool-choice启用自动工具选择
--trust-remote-code信任模型中的远程代码
--gpu-memory-utilizationGPU 显存利用率,建议 0.85-0.95

4.启动服务

脚本运行后,盯着日志docker logs -f vllm-qwen-prod

有三个阶段:

  1. Weights loading(60s):有进度条,看看是否卡住,卡住了就说明磁盘IO过慢
  2. NCCL Initialization(10s):最容易报错的地方,如果两张卡没法通信,就会出现NCCL Error。如果报错了,就在docker run里面增加环境变量 -e NCCL_P2P_DISABLE=1
  3. Capturing CUDA Graphs(60-120s):VLLM启动,预算路径,GPU占用会在此时跳动

5. 测试

  1. 吞吐量压测(用 vLLM 自带工具):

    进入容器内部,跑一个脚本,看看每分钟能处理多少请求。

  2. 脚本:

import time
from openai import OpenAI

client = OpenAI(api_key="EMPTY", base_url="http://localhost:8000/v1")

def test_inference():
    start = time.perf_counter()
    response = client.chat.completions.create(
        model="qwen-30b",
        messages=[{"role": "user", "content": "请详细解释一下量子纠缠。"}],
        stream=True
    )
    
    print("Tokens: ", end="")
    first_token_time = None
    for chunk in response:
        if chunk.choices[0].delta.content:
            if first_token_time is None:
                first_token_time = time.perf_counter() - start
            print(chunk.choices[0].delta.content, end="", flush=True)
    
    end = time.perf_counter()
    print(f"\n\n--- 性能指标 ---")
    print(f"首 Token 延迟 (TTFT): {first_token_time:.3f} s")
    print(f"总耗时: {end - start:.3f} s")

test_inference()

或者:

# 查看可用模型列表
curl http://localhost:8000/v1/models

# 基础对话测试
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm5",
    "messages": [
      {"role": "user", "content": "你好,请介绍一下你自己"}
    ],
    "max_tokens": 100,
    "temperature": 0.7
  }'

# 流式对话测试
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm5",
    "messages": [
      {"role": "user", "content": "用一句话解释什么是 Kubernetes"}
    ],
    "max_tokens": 200,
    "stream": true
  }'

GLM-5 支持开启/关闭思考模式,通过 chat_template_kwargs 参数控制:

开启思考模式(默认):

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm5",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Summarize GLM-5 in one sentence."}
    ],
    "temperature": 1,
    "max_tokens": 4096
  }'

关闭思考模式:

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm5",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Summarize GLM-5 in one sentence."}
    ],
    "temperature": 1,
    "max_tokens": 4096,
    "chat_template_kwargs": {"enable_thinking": false}
  }'

5.1 性能基准测试

使用 vLLM 内置的 benchmark 工具进行测试:

# Prompt-heavy benchmark (8k input / 1k output)
vllm bench serve \
  --model /app/model \
  --served_model_name glm5 \
  --dataset-name random \
  --random-input 8000 \
  --random-output 1024 \
  --request-rate 10 \
  --num-prompts 32 \
  --trust-remote-code \
  --ignore-eos

INT4 版本测试结果

============ Serving Benchmark Result ============
Successful requests:                     32
Failed requests:                         0
Request rate configured (RPS):           10.00
Benchmark duration (s):                  35.27
Total input tokens:                      256000
Total generated tokens:                  32768
Request throughput (req/s):              0.91
Output token throughput (tok/s):         929.09
Peak output token throughput (tok/s):    1088.00
Peak concurrent requests:                32.00
Total token throughput (tok/s):          8187.65
---------------Time to First Token----------------
Mean TTFT (ms):                          144.10
Median TTFT (ms):                        139.03
P99 TTFT (ms):                           226.47
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          31.61
Median TPOT (ms):                        31.70
P99 TPOT (ms):                           31.80
---------------Inter-token Latency----------------
Mean ITL (ms):                           31.61
Median ITL (ms):                         31.92
P99 ITL (ms):                            58.34
==================================================

关键指标解读:

指标含义测试结果
TTFTTime To First Token,首 token 延迟,衡量用户等待第一个响应的时间平均 144ms,响应迅速
TPOTTime Per Output Token,每个 token 的生成时间,反映流式输出的流畅度平均 31.6ms

6. 可能存在的问题

问题 1:启动报错 Out of Memory (OOM)

原因:4090 显存 24G 扣掉系统占用可能只剩 22G。两张卡 44G 左右。30B 的 FP8 模型占 30GB,剩下的显存不够放 max-model-len 设定的缓存。

解决方法:减小 --max-model-len 到 8192,或者降低 --gpu-memory-utilization 到 0.85。

问题 2:首 token 还是慢,为什么?

原因Prompt 太长:Qwen 预处理长文本需要时间。CPU 瓶颈:vLLM 虽然是 GPU 计算,但调度靠 CPU。如果你的 CPU 是 E5 系列那种老古董,调度会变慢。

验证:看看日志里的 PreFill 时间。

问题 3:模型胡言乱语

原因:Qwen3 可能需要特定的 Chat Template。

解决方法:在调用接口时,确保使用标准的 OpenAI 格式,vLLM 会自动调用模型文件夹里的 tokenizer_config.json 来处理格式。

Reference

意琦行 : VLLM 部署 GLM-5 实践指南 - 探索云原生