在 8GB 显存(如 RTX 4060)上跑 VLM,最大的瓶颈不是计算量,而是 显存管理。普通的推理脚本加载模型后,剩下的显存几乎放不下几个 KV Cache,导致 Batch Size 只能开到 1,速度慢得像蜗牛。

1. 技术栈选型:为什么是 vLLM?

普通的加载方式是静态分配显存,而 vLLM 像操作系统管理内存一样,把显存切成块(Blocks)。

  • 优势 1: 几乎零显存浪费。
  • 优势 2: Continuous Batching。它不需要等待一个 Batch 全部跑完,只要有空闲 Token 槽位,新的请求就能插队进来。
  • 优势 3: 完美支持 GPTQ/AWQ 量化

2. 核心部署步骤:4-bit 量化加速

为了让 DeepSeek-OCR 或 MiniCPM 在 8GB 显存里跑得稳,我们必须使用 4-bit 量化,并配合高性能内核。

第一步:安装高性能后端

Bash

# 建议在 CUDA 12.1 环境下安装
pip install vllm>=0.6.0 
pip install optimum auto-gptq # 用于支持 GPTQ 模型

第二步:启动 API 服务

别在代码里写死推理逻辑,直接把模型起成一个 OpenAI 兼容的 API 服务。 注意 gpu_memory_utilization 参数,给系统留点缝隙。

Bash

python -m vllm.entrypoints.openai.api_server \
    --model deepseek-ai/deepseek-vl-7b-chat \
    --quantization gptq \
    --tensor-parallel-size 1 \
    --gpu-memory-utilization 0.9 \
    --max-model-len 4096 \
    --limit-mm-per-prompt image=1

3. 前端调用:异步并发请求

既然后端已经是流式 API 了,前端就得用 asyncio 配合 httpx 压测。别用单线程 requests,那样会白白浪费后端的并发能力。

Python

import asyncio
import httpx
import base64

async def ocr_request(client, image_path):
    # 图片转 Base64
    with open(image_path, "rb") as f:
        img_b64 = base64.b64encode(f.read()).decode("utf-8")

    payload = {
        "model": "deepseek-vl-7b-chat",
        "messages": [{
            "role": "user",
            "content": [
                {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{img_b64}"}},
                {"type": "text", "text": "OCR this document to markdown."}
            ]
        }],
        "temperature": 0
    }
    
    response = await client.post("http://localhost:8000/v1/chat/completions", json=payload)
    return response.json()

async def main():
    image_list = ["doc1.jpg", "doc2.jpg", "doc3.jpg", "doc4.jpg"] # 批量任务
    async with httpx.AsyncClient(timeout=None) as client:
        # 同时并发 4 个请求,压榨显存 KV Cache
        tasks = [ocr_request(client, img) for img in image_list]
        results = await asyncio.gather(*tasks)
        for res in results:
            print(res['choices'][0]['message']['content'])

if __name__ == "__main__":
    asyncio.run(main())

4. 调优策略:最后一滴性能在哪?

如果你发现速度还是达不到预期,检查这三个地方:

  1. CPU 瓶颈: vLLM 采样非常吃 CPU 调度。如果你的 CPU 太烂,GPU 会经常处于等待状态(GPU Load 不满)。建议开启多线程预处理。
  2. 图像预缩放: 别把 8K 原图直接传给 API。在前端用 OpenCV 先 resize 到 1024px。DeepSeek 的光学压缩层在 1024px 以下的效率最高,这能减少传输开销和显存占用。
  3. 禁用 Chunked Prefill: 在显存极小的环境下,关闭 vLLM 的 chunked prefill 有时能减少 OOM(溢出)的风险,虽然会牺牲一点点响应时间。

5. 结论

对于咱们技术人来说,模型只是原材料,工程化落地才是核心。在 8GB 显存上,通过 vLLM + 4-bit 量化 + 异步并发,你可以把一个原本需要 A100 才能跑顺的任务,强行在消费级显卡上跑出工业级的吞吐率。