基于vLLM进行DeepSeek-671B集群化部署与调参数优化

683 阅读10分钟

从个人公众号分享过来,看好多教程都无法正确的运行起来,所以当笔记记录与分享。


一、环境配置

  1. 硬件拓扑

本次部署采用分布式架构,共涉及 3 台机器,。

  • Head 节点:xxx.xxx.xxx.14 ,配备 8 个 L20 显卡,每个显卡显存达 46GB 。

  • Worker 节点:xxx.xxx.xxx.18 和 xxx.xxx.xxx.19 ,同样各配备 8 个 L20 显卡,单个显卡显存 46GB 。这些 Worker 节点作为计算主力,分担推理任务。

总显存容量达到 24×46GB = 1,104GB 。

  1. 软件栈
组件版本
CUDA12.4
vllm/vllm-openai v0.8.0
docker 和 nvidia-contaier-toolkit/

二、部署vllm

  1. 前置条件

安装cuda 与nvidia-contaier-toolkit

查看vllm 官方文档并且下载run_cluster.sh 脚本

docs.vllm.ai/en/latest/s…

每一台机器执行 export VLLM_HOST_IP=${local_ip}

docs.vllm.ai/en/latest/s…

第三个必须执行!!!

2. 节点启动 

bash run_cluster.sh vllm/vllm-openai:v0.8.0 {head_ip}  --{role} /wx/models-e VLLM_HOST_IP={local_ip} -e GLOO_SOCKET_IFNAME=bond0 -e NCCL_SOCKET_IFNAME=bond0 

3. 参数说明

head_iphead 节点的ip 地址
role只有 head 和worker
local_ip 本地机器ip,需要和IFNAME 对应起来,不能IFNAME 选择eth0 ip 是eth1
bond0网络eth
/wx/models 模型目录地址,该目录下存在deepseek-r1 目录,最佳方案是 找一台机器做nfs server 
GLOO_SOCKET_IFNAME指定 GLOO 进行通信时所使用的网络接口
NCCL_SOCKET_IFNAME用于指定 NCCL 进行通信时所使用的网络接口|
  1. 查看状态

首先进行docker  ps 查看容器是否启动成功?然后执行ray status 和查看模型是否挂载进来,如图所示就是OK,

注意事项:/root/hugginface 目录并不是默认存放模型地址,我修改了run_cluster.sh 脚本

图片


三、运行deepseek 671B模型

  1. 进入head 容器中,执行命令
VLLM_USE_V1=1 VLLM_TEST_ENABLE_EP=1 vllm serve /root/huggingface/deepseek-r1     --trust-remote-code     --port 8000     --tensor-parallel-size 8     --pipeline-parallel-size 3     --quantization fp8     --gpu-memory-utilization 0.95     --max-model-len 32768     --max-num-seqs 16     --served-model-name deepseek-r1

  1. 参数说明 

参数说明 

/root/huggingface/deepseek-r1模型目录
--port 8000open api 端口
--tensor-parallel-size 8每个层的计算分布在8个GPU上
--pipeline-parallel-size 3将模型的多个层纵向切分到3个GPU节点上

VLLM其他部分参数

--model说明: 使用的Hugging Face模型名称或路径。
--tokenizer说明: 使用的Hugging Face分词器名称或路径。如果未指定,将使用模型名称或路径。
--tokenizer-revision说明: 使用的Hugging Face分词器的修订版本。
--tokenizer-mode说明: 分词器模式,支持选项:auto, slow, mistral, custom。默认: “auto”
--trust-remote-code说明: 信任来自Hugging Face的远程代码。
--load-format说明: 加载模型权重的格式,支持选项:auto, pt, safetensors, npcache, dummy, tensorizer, sharded_state, gguf, bitsandbytes, mistral, runai_streamer。默认: “auto”
--config-format说明: 加载模型配置的格式,支持选项:auto, hf, mistral。默认: “auto”
--dtype说明: 模型权重和激活的数值类型,支持选项:auto, half, float16, bfloat16, float, float32。默认: “auto”
--kv-cache-dtype说明: kv缓存存储的数据类型,支持选项:auto, fp8, fp8_e5m2, fp8_e4m3。默认: “auto”
--max-model-len说明: 模型上下文长度。如果未指定,将自动从模型配置中推导。
--distributed-executor-backend说明: 用于分布式模型工作者的后端,支持选项:ray, mp, uni, external_launcher。
--pipeline-parallel-size,说明: 管道阶段的数量。
--tensor-parallel-size, -tp说明: 张量并行副本的数量。
--block-size说明: 连续token块的大小,支持选项:8, 16, 32, 64, 128。--enable-prefix-caching, 
--no-enable-prefix-caching说明: 启用或禁用自动前缀缓存。
--swap-space说明: 每个GPU的CPU交换空间大小(GiB)。默认: 4
--gpu-memory-utilization说明: 用于模型执行的GPU内存占用比例,范围从0到1。默认: 0.9
--max-num-seqs说明: 每次迭代的最大序列数量。
--quantization, -q说明: 用于量化权重的方法,支持多种选项。
--device说明: vLLM执行的设备类型,支持选项:auto, cuda, neuron, cpu, openvino, tpu, xpu, hpu。默认: “auto”

3. 进行api 测试

curl http://localhost:8000/v1/chat/completions \  -H "Content-Type: application/json" \  -d '{    "model""deepseek-r1",    "messages": [      {"role""user""content""用Python写一个快速排序算法"}    ],    "stream": true,    "max_tokens": 2048  }'

四、性能测试

测试脚本来源是github vllm 项目benchmarks

github.com/vllm-projec…

  1. 测试脚本
python3 vllm/benchmarks/benchmark_serving.py --backend  openai-chat --dataset-name random --model {modelPath} --served-model-name {modelName} --num-prompts 100 --max-concurrency {concurrency} --random-input {inLen} --random-output {outLen}   --endpoint /v1/chat/completions --trust-remote-code

2. 下载数据集或者使用random 数据集进行测试

  1. 测试部分结果

图片

  1. 测试结论

直接将数据交给部署的deepseek 告诉我测试结论。

a. 首字延迟与批次大小的关系

  • 首字延迟随批次增大显著上升在输入/输出长度为256时,batch_size从8增至512,首字延迟从837ms激增至24秒。4096长度下,batch_size 512的首字延迟高达214秒。
  • 原因推测大batch_size需要更多计算资源初始化生成过程,显存带宽或并行计算能力可能成为瓶颈。

b. 吞吐量(TPS)与批次规模的平衡

  • Input/Output TPS先升后降
    • 对于256长度,TPS在batch_size=64时达到峰值238(Input)和237(Output);4096长度下,TPS峰值在batch_size=128时(304.53 Input)。
    • 优化区间:不同输入长度存在最佳batch_size(如256长度选64,4096选128),超过后TPS下降或增长停滞。
  • 硬件资源限制极大batch_size可能导致显存耗尽或计算单元过载,限制性能提升。

3. 输入长度对性能的影响

  • 长文本处理成本剧增
    • 输入长度从256增至4096时,首字延迟增长超25倍(837ms→214秒),总时延增长超9倍(150s→1453s)。
    • TPS衰减明显4096长度的Input TPS仅为256长度的35%(峰值304 vs 238)。
  • 实际建议需权衡上下文长度需求与性能,超长文本(如4096)适合非实时场景。

4. 用户级TPS与并发能力

  • 用户级TPS随批次增大而下降
    • 256长度下,batch_size=8时用户级Input TPS为10.64,batch_size=512时降至0.53。
    • 并发与效率的权衡:小batch_size适合高并发低延迟场景,大batch_size适合批量处理但牺牲单请求响应速度。

5. 总时延的批次效应

  • 总时延呈U型曲线
    • 在256长度下,batch_size=64时总时延最低(53.78s),过大(如128)或过小(如8)均导致时延增加。
    • 资源竞争加剧极大batch_size可能导致显存碎片化或调度开销上升。

6. 硬件瓶颈推测

  • 显存带宽限制首字延迟的陡增可能源于大batch_size的显存加载压力。
  • 计算单元利用率小batch_size可能无法充分利用GPU并行计算能力,大batch_size则受限于显存容量。

五、调参优化

调解vllm 参数进行测试,其他的调试也不会!!

  1. 找到问题
  •  查看测试数据和测试结论,第一个是首token 生成延迟。第一个想到是增大block size
  •  查看vllm 日志,kvcache 最高居然达到80%,必须增大!!
INFO 04-28 15:03:11 [metrics.py:481] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 193.6 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 41 reqs, GPU KV cache usage: 79.5%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:16 [metrics.py:481] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 193.7 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 41 reqs, GPU KV cache usage: 79.7%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:21 [metrics.py:481] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 193.0 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 41 reqs, GPU KV cache usage: 79.8%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:26 [metrics.py:481] Avg prompt throughput: 723.0 tokens/s, Avg generation throughput: 140.8 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 40 reqs, GPU KV cache usage: 79.6%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:32 [metrics.py:481] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 181.0 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 40 reqs, GPU KV cache usage: 79.8%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:37 [metrics.py:481] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 187.7 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 40 reqs, GPU KV cache usage: 80.4%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:42 [metrics.py:481] Avg prompt throughput: 1667.8 tokens/s, Avg generation throughput: 76.6 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 38 reqs, GPU KV cache usage: 79.8%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:47 [metrics.py:481] Avg prompt throughput: 843.3 tokens/s, Avg generation throughput: 134.5 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 37 reqs, GPU KV cache usage: 80.0%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:52 [metrics.py:481] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 148.9 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 36 reqs, GPU KV cache usage: 80.1%, CPU KV cache usage: 0.1%.
INFO 04-28 15:03:57 [metrics.py:481] Avg prompt throughput: 1581.6 tokens/s, Avg generation throughput: 123.4 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 35 reqs, GPU KV cache usage: 79.9%, CPU KV cache usage: 0.1%.
INFO 04-28 15:04:02 [metrics.py:481] Avg prompt throughput: 837.3 tokens/s, Avg generation throughput: 130.9 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 34 reqs, GPU KV cache usage: 79.7%, CPU KV cache usage: 0.1%.
INFO 04-28 15:04:07 [metrics.py:481] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 187.8 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 34 reqs, GPU KV cache usage: 79.8%, CPU KV cache usage: 0.1%.
INFO 04-28 15:04:12 [metrics.py:481] Avg prompt throughput: 1674.5 tokens/s, Avg generation throughput: 73.6 tokens/s, Running: 48 reqs, Swapped: 0 reqs, Pending: 32 reqs, GPU KV cache usage: 79.2%, CPU KV cache usage: 0.1%.
  • 并发上不去,想到优先处理短链接,增大批处理数量

  • 使用nvtop 监控gpu ,判断是否存在pcie 问题或者nvlink nvp2p 等没启用或者存在问题。

  • 是不是NCCL 通信存在问题

  1. 设置优化参数
参数当前配置值开启后测试结果优化建议
--enable-chunked-prefillTrue✔️ 分块处理降低内存峰值,4096长度时吞吐量提升23%长文本场景必选参数
--block-size=6464✔️ 4096长度处理效率提升18%已验证超过8k上下文推荐128
--quantization=awqAWQ✔️ 显存降低45%实测有效,但速度提升需搭配Marlin内核需使用LLM-Compressor量化工具
--max-num-batched-tokens=81928192✔️ 与动态批处理配合吞吐量提升32%短文本场景可降为4096
--gpu-memory-utilization=0.930.93⚠️ :L20的安全阈值为0.92,超过0.92可能触发OOM建议调整为0.9,并配合swap-space=16GiB
--enable-cuda-graph=TrueTrue⚠️:没效果需禁用动态shape请求
--swap-space=1616GiB✔️ 支持32k上下文处理,但会增加延迟显存不足时必选参数

3.通信优化参数(好像没啥效果!!)

  •  NCCL_NSOCKS_PERTHREAD=8:每个线程使用 8 个套接字,增加数据传输通道,提升通信带宽。
  •  NCCL_SOCKET_NTHREADS=4:设置每个套接字的线程数为 4 ,优化线程资源分配,提高通信性能。
  1. 量化没有什么是量化解决不了的,下面是我的硬件配置ai 给出的估算。那就直接选择AWQ ,开搞!!
量化方式吞吐提升精度损失
FP838%<0.5%
AWQ52%0.8%
GPTQ45%1.2%

六、优化后的部分测试结果

测试4096 输长度

指标非量化配置AWQ量化配置提升幅度
首字延迟204,416ms78,200ms61.7%↓
Input TPS304.53892.7193%↑
Output TPS105.33342.1225%↑
总时延1,345s402s70.1%↓
显存占用38.2GB21.7GB43.2%↓