5090显卡,基于vllm完成大模型推理

背景

前一张显卡是48GB,运行 Qwen/Qwen3-30B-A3B-Instruct-2507-fp8模型。在我换到5090显卡后,显存就不足以运行原先的模型了。

为了充分利用好5090显卡的显存容量,我选择了下述两个模型:

  • models/Qwen--Qwen3-30B-A3B-GPTQ-Int4
  • models/cpatonn--Qwen3-30B-A3B-Instruct-2507-AWQ-4bit

这两个模型的磁盘占用均不到20GB,然而我在使用运行模型的过程中均遇到了OOM,显存空间不够的崩溃。按理说32G的显存应该够用。我发现模型在推理的过程中除了要保存模型的参数,还要保存KV cache一些中间状态所以就导致了显存不够。解决方案就是设置降低模型的token长度,就可解决。

VLLM

推理脚本

vLLM 采用了一种叫做 PagedAttention 的技术,它会像操作系统管理内存一样,将 GPU 显存划分为一个个固定大小的 "页面"。

在推理开始前,vLLM 会根据你设定的 max_model_len 和 batch_size,一次性地、预先分配好 足够容纳所有可能 token 的 KV Cache 显存空间。它会假设每个序列都会达到 max_model_len 的长度,并按此最大值来预留空间。

对短输入的影响

即使你的输入序列很短(比如只有 100 个 token),vLLM 依然已经为它在显存中预留了 max_model_len 个位置。

内存带宽开销:虽然实际只使用了 100 个位置,但 GPU 在访问这些缓存时,其内存控制器的访问模式和带宽占用,在某种程度上依然受到为 max_model_len 预分配的大块连续内存的影响。管理一个巨大的、大部分是空的缓存,本身就比管理一个大小合适的缓存要消耗更多的 "管理成本"。

并行计算效率:GPU 是为并行计算设计的。当 max_model_len 很大时,即使实际数据很短,一些为处理长序列而优化的并行计算单元(如 Tensor Cores)可能无法被充分利用,或者需要执行一些额外的逻辑来处理 "空" 的数据,从而影响了整体效率。

现代深度学习框架(如 PyTorch/TensorFlow)在执行计算时,会先构建一个 "计算图",它定义了所有操作的执行顺序和依赖关系。

  • 静态计算图:vLLM 为了追求极致性能,会在启动时根据 max_model_len 等参数,预先构建并 "固化" 一个最优的计算图。这个图一旦生成,在整个推理过程中就不会再改变。
  • 长序列的计算图开销:一个为 max_model_len=8192 构建的计算图,其内部的矩阵乘法、循环等操作的维度都是按照 8192 来优化的。当你用这个图去处理一个很短的序列时,这些为长序列设计的计算步骤中,有一部分就成了 "多余" 的开销。
  • 更优的短序列计算图:当你将 max_model_len 降低到 2048,vLLM 会构建一个全新的、为 2048 长度优化的计算图。这个新图的计算步骤更紧凑,循环次数更少,内存访问模式更高效,因此即使对于短输入,执行这个 "小而美" 的计算图也会比执行那个 "大而全" 的计算图要快得多。

max_model_len:规定了模型在单次推理过程中所能处理的输入序列长度和输出序列长度之和的上限。设置小一点,显存是够用的。

python 复制代码
from vllm import LLM, SamplingParams

prompts = [
    "Hello, who are you?",
    "The president of the United States is",
    "The capital of France is",
    "The future of AI is",
]

sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

# model_name = "cpatonn/Qwen3-30B-A3B-Instruct-2507-AWQ-4bit"
model_name = "Qwen/Qwen3-30B-A3B-GPTQ-Int4"

llm = LLM(
    model=model_name, 
    gpu_memory_utilization=0.9,
    #  max_num_seqs=32, 
    # max_model_len=8192
    max_model_len=2048
)
outputs = llm.generate(prompts, sampling_params)

for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

能成功运行,显存占用也达到了31.1G,再多一点,显存也不够用了。

API部署

同样也需要指定max_model_len参数

复制代码
vllm serve Qwen/Qwen3-30B-A3B-GPTQ-Int4 --max_model_len 512

langchain调用API

python 复制代码
import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser


# 1. 配置 LLM
# 使用 ChatOpenAI 并指向本地的 vLLM OpenAI 兼容接口
llm = ChatOpenAI(
    # model="Qwen/Qwen3-30B-A3B-GPTQ-Int4",  # 与实际模型对应
    model="cpatonn/Qwen3-30B-A3B-Instruct-2507-AWQ-4bit",  # 与实际模型对应
    base_url="http://localhost:8000/v1",  # 关键:指向本地 vLLM API 服务
    api_key="dummy_key",  # vLLM 服务通常不需要真实密钥,填写任意非空字符串即可
    temperature=0.7,
    max_tokens=2025, # 需要比设置的2048小一点
    # max_completion_tokens=128
)

# 2. 创建 Prompt
# 使用新的 ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个 helpful 的助手。"),
    ("user", "请用中文回答以下问题: {question}")
])

# 3. 创建输出解析器
output_parser = StrOutputParser()

# 4. 使用 LCEL 语法创建 Chain
chain = prompt | llm | output_parser

# 5. 运行 Chain
response = chain.invoke({"question": "什么是大语言模型?"})

print(response)
相关推荐
冬奇Lab4 小时前
Workflow 系列(03):状态管理——持久化、幂等性与版本绑定
人工智能·工作流引擎
冬奇Lab5 小时前
每日一个开源项目(第146篇):openpilot - 开源自动驾驶辅助系统,曾在 Consumer Reports 评测中超过特斯拉 Autopilot
人工智能·开源·自动驾驶
吴佳浩6 小时前
AI 工程师知识地图:模型格式、框架、部署工具一次讲明白
人工智能·aigc·ai编程
IT_陈寒6 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
码农胖大海7 小时前
AI额度不够用的解决方案
人工智能
后端小肥肠7 小时前
小红书虚拟商品怎么做?我先用 Skill 跑通了壁纸品类
人工智能·aigc·agent
feiyu_gao7 小时前
从零搭建个人 AI 工作台:一个管理者的 3 个月实验
人工智能·aigc·团队管理
程序员cxuan8 小时前
一句话,让你用上 GPT-5.6
人工智能·后端·程序员
机器之心8 小时前
AI圈刚开始谈Loop Engineering,两位95后博士已经盯上了人类闭环数据
人工智能·openai