最近在试着把Qwen2.5-7B部署到一台双卡3090的机器上,用的vLLM框架,打算做点小规模对话服务。我参考官方文档选了AWQ 4bit量化,结果跑起来发现显存占用快18GB,比官方说的12-13GB大不少。而且首token延迟要3秒多,官方demo才0.5秒左右。我检查了模型路径、量化方式和batch size(设为1),感觉没毛病,是不是哪里参数写错了?或者是不是我显卡驱动版本太低(535),跟vLLM的paged attention有兼容问题?求大佬指点迷津,实在不想再瞎试了……
用vLLM部署Qwen2.5-7B,量化后显存占用和延迟对不上官方数据?
全部回复
共 167 条这个问题很有代表性,几乎每个刚上手vLLM的人都会碰到类似“官方数字看着很美,自己一跑直接裂开”的情况。我先说结论:你的显存18GB和首token延迟3秒多,大概率不是模型文件坏了,也不是显卡驱动535和vLLM有“不兼容”这种玄学问题,而是vLLM默认配置和官方测试环境之间存在几个非常隐蔽的差异点。我过去一年多在内部集群和边缘设备上反复折腾过Qwen系列的各种量化部署,踩过的坑比你还多,下面把几个最关键的排查方向拆开讲。
首先,显存18GB对AWQ 4bit Qwen2.5-7B来说,确实偏大,但并非不可能。官方说的12-13GB通常是指纯模型权重加载后的静态显存占用,也就是把模型参数从硬盘读到显存里,不做任何推理时的基础占用。7B模型FP16权重大约14GB,AWQ 4bit量化后理论权重只有约3.5GB,但vLLM为了支持paged attention和连续批处理,会预留大量额外显存用于KV cache、中间激活值、以及预分配的内存池。你设置了batch size为1,但vLLM有一个关键参数叫max_num_seqs(默认通常是256或更大),这个参数控制的是vLLM内部为同时处理的最大序列数预留的显存,即使你实际只发1个请求,它也会按256个序列的KV cache去分配显存。另外还有一个gpu_memory_utilization参数,默认是0.9,也就是说vLLM会尽量占用90%的可用显存来构建缓存池,而不是精确只加载模型权重。你的双卡3090单卡24GB,如果vLLM默认把所有显存都算进去(包括另一张卡?注意vLLM默认是单卡部署,除非你明确指定tensor parallel),那么18GB其实包含了大量预分配的KV cache空间。你可以试试在启动vLLM时加上--gpu-memory-utilization 0.5甚至更低,比如0.3,同时把max_num_seqs显式设为2或4,看看显存会不会立刻降下来。我做过实验,Qwen2.5-7B AWQ在单卡3090上,如果gpu_memory_utilization设为0.4,max_num_seqs=4,显存占用可以控制在12GB出头,首token延迟也会因为显存碎片减少而略有改善。
其次,首token延迟3秒多,这个差距比显存更让人抓狂。官方demo的0.5秒通常是在理想环境下测的,比如A100 80GB,CUDA 12.1,vLLM最新版本,并且可能用了FP8或者更激进的量化策略。你的环境是双卡3090,但vLLM默认并没有启用tensor parallel(需要加--tensor-parallel-size 2),如果你只用了单卡,那3090的显存带宽(约936GB/s)比A100(2TB/s)差了一倍多,加上AWQ量化后的计算效率对3090的Tensor Core并不友好(AWQ的packing格式在Ampere架构上需要额外的dequantize步骤,而H100有原生的FP8支持),所以首token延迟3秒其实并不离谱。但你可以在vLLM的启动参数里加几个优化:一是启用--enable-prefix-caching(如果对话有固定system prompt,能大幅减少首token计算量),二是把--max-model-len设小一点,比如2048或4096,而不是默认的32768(Qwen2.5-7B支持32K上下文,但如果你对话长度很短,预留太长的KV cache不仅浪费显存,还会导致attention计算量剧增)。另外,检查一下你的vLLM版本,0.4.x和0.5.x在AWQ推理上有较大的性能差异,0.5.x之后集成了FlashAttention 2的优化,对首token延迟有显著改善。如果你还在用0.4.x,升级到0.6.0或最新版(写回复时0.6.3已发布),通常能直接砍掉一半延迟。
还有一个容易忽略的点:你的模型路径是否正确加载了量化配置?AWQ量化后的模型文件通常会包含一个quantize_config.json,里面指定了group_size(一般是128)、zero_point、对称量化等参数。如果你是从HuggingFace直接下载的官方AWQ版本(比如Qwen/Qwen2.5-7B-Instruct-AWQ),那没问题。但如果你是自己用autoawq或者其他工具量化的,务必确认--quantization awq参数和模型内的config匹配。vLLM对AWQ的支持目前只认group_size=128且sym=False(非对称量化)的配置,如果你用了group_size=64或者sym=True,vLLM会fallback到FP16推理(这会导致显存和延迟都爆炸)。你可以用这个代码快速验证一下:
python
from transformers import AutoConfig
config = AutoConfig.from_pretrained("你的模型路径")
print(config.quantization_config)
如果返回None或者字段不全,那vLLM实际上是在跑FP16,显存18GB也就说得通了。
驱动版本535确实有点老,但不会导致这种级别的偏差。vLLM的paged attention依赖CUDA Graph和自定义kernel,535驱动搭配CUDA 11.8或12.1都能正常工作。你更应该检查的是CUDA runtime版本是否和vLLM编译时用的版本一致。如果你是用pip安装的vLLM,它默认绑定了CUDA 12.1的预编译包,而你的系统如果装的是CUDA 11.8,会触发动态库回退,性能下降20-30%。建议跑一下vLLM的benchmark脚本,或者直接在Python里打印torch.version.cuda,看看是不是12.1。如果不是,要么升级系统CUDA,要么用pip install vllm --no-deps然后手动安装对应版本的torch。
另外,双卡3090你打算怎么用?如果只是做简单的对话服务,单卡其实就够了,因为Qwen2.5-7B AWQ单卡延迟在1秒以内(经过上述优化后)。如果你为了吞吐量想用tensor parallel,那要注意3090之间是通过PCIe通信的(不像A100有NVLink),跨卡通信延迟会显著增加首token延迟。我建议你先把双卡拆开,部署两个独立的vLLM实例,分别监听不同端口,然后用nginx做负载均衡。这样每张卡单独处理请求,首token延迟反而比tensor parallel更低,尤其是当请求并发数不大时。如果你的使用场景是单用户连续对话,batch size=1,那tensor parallel带来的收益几乎为零,只有显存翻倍(两张卡能加载更大的模型),但延迟会因为是跨卡通信而变差。
最后,给你一个可复现的启动命令参考,假设你用的是Qwen2.5-7B-Instruct-AWQ官方版本,单卡3090,显存24GB,目标首token延迟1秒以内,显存占用12-13GB:
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq \
--gpu-memory-utilization 0.45 \
--max-model-len 4096 \
--max-num-seqs 4 \
--enable-prefix-caching \
--dtype auto \
--trust-remote-code
启动后,用vLLM自带的benchmark脚本测试:
python -m vllm.benchmarks.benchmark_latency \
--model Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq \
--input-len 128 \
--output-len 128 \
--batch-size 1
如果首token延迟还在2秒以上,那就要检查你的CUDA版本和vLLM版本了。另外,记得把系统里其他占用显存的服务关掉,比如nvidia-smi看看有没有别的进程在吃显存。
总的来说,官方数据是在特定硬件、特定软件栈、特定参数组合下的“最佳成绩”,而你实际部署时默认参数往往是为吞吐量设计的(预留大量显存和KV cache),直接套用自然对不上。只要把gpu_memory_utilization和max_num_seqs调低,确认AWQ加载成功,升级vLLM到最新,你的延迟和显存应该能回归到合理范围。如果还不行,欢迎把nvidia-smi输出、vLLM启动日志贴出来,可以再帮你细看。
这个情况我前两天刚遇到过类似的坑,可以分享点排查思路。首先AWQ 4bit显存18G确实偏高了,7B模型理论上4bit应该在4-5G左右,加上KV cache和中间激活值,单卡12-13G是合理的。你双卡3090跑18G,我怀疑是模型没有真正加载成4bit,或者vLLM默认用了FP16的KV cache。可以检查一下--quantization awq参数是否正确传递,以及用nvidia-smi看看实际显存分配,是不是有两份模型副本。
首token延迟3秒也很反常,3090单卡跑7B模型推理,首token应该秒级以内。你可以试下把--max-model-len设小一点,比如2048,vLLM默认可能会按4096甚至更长预分配显存和计算资源,这会导致首token延迟暴涨。另外驱动535确实有点老,vLLM的paged attention对CUDA版本比较敏感,建议升到545或550以上,我之前从535升到545后,同样配置下显存占用直接降了2-3G。
还有个细节:你检查下模型路径是不是真的指向了AWQ量化版本,有些人下的是原始BF16模型,然后手动传了--quantization awq,这样vLLM会先加载原始模型再运行时量化,反而更吃资源。最好用官方提供的已经量化好的模型文件,比如Qwen/Qwen2.5-7B-Instruct-AWQ这个路径。
最后确认下vLLM版本,0.6.0之后对Qwen2.5支持更好,老版本可能有bug。如果还不行,试下单卡跑,双卡通信开销在小batch下反而会拖慢延迟。
显存问题可能是vLLM默认预留了KV cache空间,试试调低gpu_memory_utilization参数。
显存试试加--enable-chunked-prefill,延迟高可能是vLLM版本太旧了。
显存这块我实测也遇到过类似偏差,AWQ量化后的模型文件大小和实际加载时的显存占用确实有差距,vLLM的pre-allocated显存和KV cache也会吃掉一部分。延迟3秒感觉不太正常,建议先确认下是不是没开--max-model-len或者设得太低,导致vLLM默认按4096算的,另外驱动535确实有点老,vLLM最新的paged attention对驱动版本有隐性要求,我之前升到545后延迟直接降了一半多,可以试试。
显存这块我踩过类似的坑,AWQ量化后实际占用和官方数据差几个G挺常见的,他们可能测的是纯模型权重+最小kv cache的理想环境,你双卡3090跑vLLM的话,paged attention本身也会预分配一些显存做缓存,试试把gpu_memory_utilization调到0.85以下看看能不能压下来。首token延迟3秒确实有点离谱,我怀疑是显卡驱动版本太低影响cuda graph优化,建议升到545以上,另外检查下vLLM是不是编译的时候没开flash attention,这个对首token速度影响很大。
显存这块我踩过类似的坑,vLLM默认会给每个卡预留一部分kv cache空间,如果你没手动设max_num_seqs或gpu_memory_utilization,它可能自己吃掉了不少显存。延迟的话,3秒首token确实离谱,建议先确认下模型是否真的加载了AWQ版本,有时候路径指错或没装对应的量化kernel,会回退到FP16跑。驱动535版本应该够用,但可以查下CUDA版本和vLLM的兼容列表,我之前升到12.1就稳了。另外试试把tokenizer的trust_remote_code打开,Qwen的配置里有些自定义组件容易出幺蛾子。
显存差这么多大概率是vLLM版本问题,试试0.6.0以上版本,对Qwen2.5的量化支持有优化。
显存这块我踩过类似的坑,vLLM默认会预分配一部分缓存,你试试加上--gpu-memory-utilization 0.85这个参数,能压下来不少。延迟3秒确实离谱,检查一下是不是把模型加载到了CPU或者显存没吃满,可以看看vLLM的日志里有没有“CPU offload”字样。另外535驱动跑paged attention确实有点老,我升到545之后小问题少了很多,建议先升级驱动再排查。
显存差距这么大,可能是vLLM默认预分配了上下文缓存,试试调低max-model-len和gpu-memory-utilization。
显存那个18GB我也遇到过,其实vLLM默认会预留一部分显存做KV cache和碎片管理,官方那个12-13GB是纯模型加载的数据,你设个--gpu-memory-utilization 0.9试试。延迟高的话检查下是不是没开--enable-prefix-caching,或者vLLM版本太旧了,0.6.x之后对qwen2.5的page attention优化挺多的。驱动535倒不至于不兼容,但建议升到545以上,对CUDA 12.4的支持更稳。
老实说,我前段时间也踩过一模一样的坑,vLLM配Qwen2.5-7B的AWQ量化之后显存直接飙到快17G,官方那个12-13G我怀疑是纯推理场景、完全不加载kv cache的极端数据。你那个18GB其实挺正常的,vLLM默认会预分配一部分显存做paged attention的缓存池,如果没手动调max_model_len或者gpu_memory_utilization,它会给得很宽裕,尤其双卡场景下每张卡还得留空间做tensor parallel。首token延迟高我觉得更可能是驱动版本的问题,535确实有点老,vLLM的paged attention在535上跑大模型时page table管理会多出不少开销,我之前升到545之后首token直接降了快一半。另外你检查下是不是用了--enable-chunked-prefill,这个在高延迟场景下会加剧首token耗时,可以关掉试试。还有个容易忽略的点,如果你模型是从huggingface直接拉的原版AWQ safetensors,注意确认下它是不是真的4bit,有些社区上传的模型其实是gptq混标。建议先单卡跑一次,只设一个worker,然后把quantization参数显式写成awq_marlin,vLLM对这个格式的优化比普通AWQ好很多。
检查下vLLM版本和CUDA版本吧,老驱动配新框架经常出这种偏差。
显存高可能是context length设太大,默认8192改成2048试试,延迟可以开下--enable-prefix-caching。
显存问题可以检查下是否加载了完整模型到两张卡上,单卡运行试试看。
显存这块我也踩过坑,vLLM默认会预留一部分显存给kv cache做预分配,18GB其实包含了这部分预留,实际模型本体没那么大。首token延迟3秒的话,建议检查下是否开了--gpu-memory-utilization参数,默认值0.9可能太高了,调低到0.8试试。另外535驱动确实有点老,vLLM在550以上版本对paged attention的优化更激进,升级驱动说不定能解决你的延迟问题。
显存差这么多确实离谱,试试换最新的550驱动,vLLM对驱动版本很敏感。
显存这块我怀疑是不是vLLM默认给每个卡都分配了冗余的KV cache,我记得paged attention的特性就是预留空间,你可以看看启动参数里加个--max-model-len 2048或者调低gpu_memory_utilization试试,我调完从16G降到了13G左右。延迟问题可能跟驱动还真有点关系,535确实有点老,我之前升到545之后首token快了将近一倍,不过也有可能是你用的模型版本或者vLLM版本跟官方demo不完全一致,建议先换个官方推荐的vLLM稳定版本跑一下基准对比。
这个问题我前阵子也踩过坑,感觉官方那个数据可能是用特定配置跑出来的理想值。AWQ 4bit按理说显存确实应该低不少,但18GB这个数很像是显存碎片和KV cache预留导致的——vLLM默认会预分配一部分显存给paged attention,双卡3090的话可能每张卡都留了余量,你可以试试--gpu-memory-utilization 0.9或者更低,甚至设成0.7看看能不能降下来。延迟方面,首token慢很可能是模型加载时没做预填充(prefill)优化,或者你输入长度比较长,毕竟Qwen2.5-7B的上下文窗口挺大的,首token计算量跟输入长度直接挂钩。另外535驱动确实有点老了,vLLM的paged attention在一些旧驱动上会有奇怪的性能问题,建议至少升到545或550试试,特别是如果启用了flash attention的话。batch size设1没问题,但你可以检查一下vLLM的max-model-len是不是设得太大了,比如默认可能是8192,而你实际用不到那么多,调小它能省不少显存和计算。最后,确认下你用的vLLM版本是不是最新的,0.6.x之后对Qwen2.5的支持和优化比早期版本好很多,升级可能直接解决问题。
我也遇到过类似情况,双卡3090跑AWQ 4bit确实容易显存虚高,检查下vLLM的gpu_memory_utilization参数,默认0.9可能预留太多,手动调到0.85或更低试试。首token延迟3秒我怀疑是vLLM的prefill阶段没优化好,可以试试把--max-model-len设小点,比如4096,能省不少计算量。驱动535版本我之前也踩过坑,跟vLLM的某些CUDA kernel确实有兼容问题,建议升到545或550。另外确认下你下的AWQ模型是不是官方仓库那个,有些第三方量化版本格式不对也会导致额外开销。