GPU 推理性能调优:显存管理、量化与并发

推理慢,十有八九不是模型的问题,是显存和并发没配好。同样一张卡,配好了每秒几十个 token,配不好直接 OOM 或者排队半天。这篇讲 GPU 推理的性能调优:显存管理、量化、批处理与多卡。

一、先看瓶颈在哪

# 实时看显存、利用率、温度、功耗
nvidia-smi

# 每秒刷新一次,只看关键列
nvidia-smi --query-gpu=index,name,memory.used,memory.total,utilization.gpu,temperature.gpu \
  --format=csv -l 1

# 看哪个进程占了显存
nvidia-smi --query-compute-apps=pid,used_memory --format=csv

先分清瓶颈:显存满了是容量问题,利用率低是调度问题,温度高降频是散热问题。三个问题三个治法,别一上来就加卡。

二、显存管理:模型 + KV cache

推理的显存分两块:模型权重和 KV cache(对话历史的缓存)。7B 模型 FP16 权重约 14GB,剩下的显存基本都给 KV cache。上下文越长、并发越高,KV cache 吃得越多。vLLM 的 --gpu-memory-utilization 就是控制总占用,--max-model-len 控制单条上下文上限,两个数要一起调。

  • 先算权重:参数量 × 精度字节数。7B 模型 FP16 约 14GB,BF16 一样,INT8 约 7GB,INT4 约 4GB。
  • 再留 KV cache:总显存减去权重,剩下的就是 KV cache 的预算,并发数和上下文长度都从这里出。
  • 别占满:利用率设 0.9,留 10% 给系统和突发,0.95 以上容易 OOM。

三、量化:精度换速度

# AWQ 4-bit 量化推理(vLLM 原生支持)
python -m vllm.entrypoints.openai.api_server \
  --model Qwen/Qwen2.5-7B-Instruct-AWQ \
  --quantization awq \
  --gpu-memory-utilization 0.9 \
  --port 8000

量化分两档:INT8 几乎不掉效果,显存减半;INT4(AWQ/GPTQ)显存再减半,效果掉一点,日常问答基本感觉不出来。选型原则:显存够就 FP16/BF16,不够就 INT8,还不够就 INT4,别在精度上死磕,先让服务跑起来。

四、并发与批处理

推理的吞吐主要靠批处理:一次前向算多个请求,分摊开销。vLLM 的 continuous batching 是动态的,请求来了就插队,不用等一整批。关键参数就两个:--max-num-seqs(最大并发数)和 --max-num-batched-tokens(一批最多多少 token)。并发调高,吞吐上去,首 token 延迟也会上去,压测定个平衡点。

# 压测:看不同并发下的吞吐和延迟
python -m vllm.benchmarks.benchmark_serving \
  --backend openai-chat \
  --model Qwen/Qwen2.5-7B-Instruct \
  --dataset-name random \
  --num-prompts 200 \
  --request-rate 10 \
  --base-url http://localhost:8000

五、多卡:张量并行与流水线

  • 张量并行:一个模型切到多张卡上,适合单个模型太大、一张卡放不下。--tensor-parallel-size 2 就是两张卡分一个模型。
  • 多实例:每张卡跑一个独立实例,适合小模型多并发,互不干扰。
  • 8 卡怎么分:先看模型大小,7B 量化版单卡就能跑,8 卡跑 8 个实例比切一个大模型吞吐高;70B 才需要张量并行。

调优就三步:先看 nvidia-smi 定瓶颈,再调显存和量化把模型塞进去,最后压测定并发。改一个参数测一次,别一次改一堆,出了问题不知道是谁的锅。

发表回复

后才能评论