最近在做一个内部工具,想把Llama-3-8B微调后的模型部署到公司服务器上给同事用。但手头只有一张RTX 4090(24G),用vLLM加载fp16权重直接OOM,量化到int8勉强能跑但并发一高就慢得离谱。试了llama.cpp的GGUF格式,速度倒是上来了,但功能上有些算子不支持,改起来很麻烦。想问问各位大佬,除了换更大显存的卡,有没有什么成熟的方案?比如张量并行、offload到CPU或者用更激进的量化?另外,如果考虑上多卡,是不是还得改代码?目前有点迷茫,求指点。
大模型部署到生产环境,显存不够怎么办?只能换卡吗?
全部回复
共 41 条4090跑8B确实憋屈,试试AWQ量化+FlashAttention,显存砍半并发能翻倍,代码不用动。
4090跑8B其实挺尴尬的,我之前试过把int8量化跟vLLM的chunked prefill配合起来,吞吐能好不少,你可以看看是不是没开这个选项。张量并行的话单卡就别想了,但如果你公司有闲置的旧卡比如3090,组个双卡用accelerate或者vLLM的多卡模式基本不用改代码,就是得注意PCIe带宽别成瓶颈。
4090跑8B其实挺尴尬的,24G看着够用但fp16就是卡在边缘。我建议你试试AWQ或者GPTQ的4bit量化,配合vLLM的awq后端,显存占用大概能压到6-7G,吞吐比int8好不少,而且算子兼容性比GGUF强。如果非要上多卡,张量并行确实要改代码,但vLLM里其实就改个启动参数的事,不用太担心。另外可以看看offload到CPU的方案,比如DeepSpeed的ZeRO-Infinity,但延迟会高,适合内部工具这种对实时性要求不高的场景。
试试Q4_K_M量化加mmap,4090跑8B并发20以内没问题,算子不支持就换llama.cpp新版本。
说实话你这个场景我太熟了,4090跑8B fp16确实卡在临界点上,vLLM的显存管理有时候比想象中更吃紧。我觉得你没必要一步到位换卡,可以先试试把KV cache的分配策略调一下,vLLM里有个gpu_memory_utilization参数,留个0.85左右给其他开销,有时候能挤出不少空间。int8慢的话,我怀疑是不是量化后算子没有走TensorRT或者没有用上FlashAttention,你可以查一下是不是触发了fallback路径,那玩意儿性能差距能到两三倍。至于offload到CPU,建议别太指望,除非你的业务对延迟完全无所谓,否则PCIe带宽就是瓶颈,batch稍微大点CPU直接变成木桶。多卡的话,张量并行其实vLLM和llama.cpp都支持,不需要改模型代码,但你要注意卡间通信走NVLink还是PCIe,4090没有NVLink,跨卡通信效率会打折扣,8B模型用两张卡反而可能因为通信开销得不偿失。另一个思路是试试AWQ或GPTQ的4bit量化,配合vLLM的AWQ kernel,我记得8B模型能压到6G左右,并发能力比int8强不少,而且算子支持比GGUF完整。最后提醒一句,你微调过的模型如果用了特殊token或者自定义层,量化前一定要跑一遍校准集,不然精度崩了同事会找你麻烦的。
说实话24G跑8B fp16确实卡在临界点上,vLLM的显存管理本身就比HF推理要贪一些。你试过PagedAttention的pre-allocated比例调低点吗?有时候默认预留50%给KV cache,实际业务并发没那么高的话能省出一大截。另外int8慢不一定全是量化的问题,vLLM对int8的支持本身就没优化好,TensorRT-LLM配合FP8可能更稳,不过改代码成本得权衡下。
多卡的话不用太慌,如果只是张量并行,vLLM和accelerate基本是透明支持的,数据并行更简单,但显存占用不会降。真正麻烦的是如果微调时用了LoRA之类的,部署时得把adapter合并回去,不然多卡加载会出莫名其妙的问题。offload到CPU我试过,慢得没法用,除非你是纯流式生成场景,否则别碰。
更激进的量化比如AWQ或者GPTQ的4bit,8B模型压到5-6G显存,4090跑起来绰绰有余,精度损失其实体感不明显,前提是你别用那种激进到会崩的校准集。不过GGUF算子不支持这个确实头疼,尤其你后面要加自定义逻辑的话,建议直接转成TensorRT-LLM的engine,虽然前期折腾点,但部署完是真省心。最后提醒一句,如果同事同时用的多,不如做个简单的请求队列,比你折腾显存便宜多了。
4090跑8B还这么折腾,要不试试AWQ量化加vLLM的auto前缀缓存,并发能救回来不少。
试试4bit AWQ量化吧,配合vLLM并发能好很多,算子兼容性也比GGUF强。多卡也不用改代码,vLLM直接tensor parallel就行。
试试4bit AWQ配合vLLM的awq内核,8B模型能压到6G,并发和速度都比int8好不少。
试试4bit AWQ量化吧,vLLM原生支持,4090跑8B并发几十没问题,不用折腾算子。
多卡的话其实vLLM开个tensor-parallel-size参数就行,代码不用改,但你这单卡先上AWQ最省事。
4090跑8B其实挺尴尬的,卡在显存和带宽的临界点上。你试过的路子基本都踩过一遍了,我补充个思路:vLLM现在支持FP8量化,配合flash attention,吞吐比int8的GPTQ稳定不少,而且算子覆盖比GGUF全。如果坚持fp16,可以试试把KV cache offload到内存,用--kv-transfer-config开一下,单卡能扛到4K上下文,但并发别指望太高。多卡的话,张量并行确实得改代码,不过vLLM的TP=2几乎零改动,只要你有两张卡,建议先借一张试试,比换卡便宜多了。另外别忽略PagedAttention的显存碎片问题,调大--gpu-memory-utilization到0.95,有时候能挤出一两个G。最省事的方案其实是换模型,比如用Llama-3-8B-Instruct的AWQ版,4bit下精度损失很小,配vLLM延迟能压到80ms以内。你那个算子不支持的坑,八成是GGUF的特定层融合问题,建议直接看llama.cpp的issue里有没有对应workaround,或者干脆切回exllamav2,它的量化内核更激进,支持也全。最后提醒一句,如果只是内部工具,真没必要追求高并发,限流到5个并发,int8其实够用,别和自己过不去。
4090跑8B其实不用死磕vLLM,llama.cpp的GGUF确实是最省心的路子,算子不支持大概率是你用的量化版本太激进,试试Q5_K_M或者Q6_K,速度和质量平衡好很多。真要上多卡的话,vLLM的tensor parallel其实改个参数就行,不需要动代码,但两张4090之间NVLink带宽是瓶颈,pcie的话提升有限。另外也可以看看offload到内存的方案,比如把KV cache放CPU,显存占用能降一半,就是延迟会高点。
试试FP8量化加offload,4090跑8B其实够用,就是得牺牲点首token延迟。多卡的话vLLM基本不用改代码,直接上。
单卡瓶颈就在显存带宽,建议看看AWQ或GPTQ的4bit,配合paged attention,并发能好不少。
说实话4090跑8B卡在显存上挺常见的,不用非得换卡。你可以试试vLLM开offload,把一部分层放到CPU上,虽然慢点但至少不OOM,而且代码不用大改。多卡的话其实也没那么可怕,vLLM支持张量并行,两张卡就能拉起来,但得注意PCIe带宽,不然通信开销反而拖后腿。另外可以看看AWQ或GPTQ这类4bit量化,配合vLLM的量化内核,比int8快不少,之前我这么搞过,显存占用直接砍半,并发也稳住了。
说实话你这情况跟我上个月一模一样,4090跑8B fp16就是卡在边缘,vLLM那点显存管理根本不够看。我当时试了一圈下来,最省事的不是换卡,是上AWQ或者GPTQ的4bit量化,配合vLLM的awq后端,显存直接砍到6G左右,并发能拉到20以上,速度比int8还快一截。你要是担心精度损失,可以用lm-eval跑一下你微调任务相关的benchmark,基本没差。
至于offload到CPU,我劝你别碰,除非你公司服务器内存带宽是那种企业级的,不然延迟能让你同事骂娘。张量并行倒是正经方向,但8B模型单卡就能塞下,上多卡纯属浪费,除非你未来要换70B。多卡的话vLLM其实不用改代码,你只要把tensor-parallel-size设成卡数,它内部自动切分,但前提是你得用同一个节点内的卡,跨节点得上Ray,复杂度直接翻倍。
还有个野路子,你试试把prompt cache打开,加上continuous batching,vLLM默认是开的,但有时候配置没生效。最后提醒一句,llama.cpp那些算子不支持的问题,你不如直接换ExLlamaV2,速度和功能平衡得比llama.cpp好,而且支持动态量化,说不定能救你一把。
说实话你这情况我太熟了,4090跑8B fp16本来就是极限边缘,vLLM那套还要留KV cache的余量,OOM不冤。int8慢不是量化本身的问题,大概率是vLLM的kernel没针对你的算子做优化,换AWQ或者GPTQ试试,配合FlashAttention,吞吐能上来不少。
关于offload到CPU,我劝你别抱太大希望,除非你只跑单并发内部调试,否则内存带宽瓶颈会让延迟直接爆炸。张量并行倒是真能解渴,但前提是你得有第二张卡,而且代码层面vLLM和TGI都原生支持,不用改模型结构,只是启动参数加个tensor-parallel-size就行。
你要是真不想动卡,还有一个野路子——用FP8混合精度,H100才支持满血FP8,但4090能跑E4M3格式的权重量化,配合bitsandbytes的NF4,显存占用能压到5-6G,速度比int8还快,就是精度损失得自己测。另外,如果只是内部工具,可以试试把模型切成两半,前几层放GPU,后几层放CPU,用llama.cpp的--tensor-split参数,但算子支持问题你还是得忍。
最后多卡的事,vLLM和TGI都帮你封装好了,不需要改业务代码,但要注意你的模型如果是用PEFT微调的,得先merged成完整权重再转格式,不然多卡加载会出问题。先别急着换卡,把量化方案和KV cache策略调一调,大概率能撑住。
说实话你这个场景我太熟了,4090跑8B fp16就是卡在边缘,vLLM其实可以先试试PagedAttention加上--max-num-seqs调小点,有时候能挤出不少空间。int8慢大概率是量化后kernel没吃到优化,可以看看AWQ或者GPTQ配合vLLM的量化推理,比动态量化稳不少。多卡的话不用太慌,vLLM对张量并行支持很透明,两张4090改个启动参数就行,代码基本不用动,就是注意NVLink带宽瓶颈。真要省事,干脆把不常用的层offload到CPU,虽然慢点但至少不OOM,内部工具够用就行。
4090其实没你想的那么不堪,vLLM吃显存主要是因为它把KV cache和activation都预留得很足,你试试开--max-num-seqs调小一点,再把--gpu-memory-utilization设到0.9,8B int8跑个8-16并发应该能挤进去。要是实在不行,把offload开起来,vLLM现在支持CPU offload,慢是慢点但至少不OOM。至于llama.cpp算子不全的问题,你可以看看它最近更新支持了哪些,或者干脆用ExLlamaV2,它对8B支持得挺全,量化到4bit速度也不差。多卡的话,其实不用改太多代码,主流推理框架都支持tensor parallel,你只要把模型用torchrun或者vLLM的--tensor-parallel-size=2启动就行,但得注意你的pcie带宽,如果是x4的槽位,多卡反而可能更慢。另外你既然只是内部工具,试试FP8量化?现在H100和4090都支持,比int8损失小,吞吐也能提升。最后提醒一句,如果同事只是偶尔用用,其实开个API网关做排队,让单卡一次只跑一个请求,体验反而比硬撑并发好。
4090跑8B其实挺尴尬的,24G卡在fp16和int8之间不上不下,我最近用AutoAWQ做4bit量化配合vLLM,吞吐比int8好不少,而且算子兼容性比GGUF省心。你如果不想动代码,可以先试试把max-model-len调小点,再把KV cache的预留空间压一压,很多时候OOM是显存碎片浪费的锅。真要上多卡的话,vLLM的tensor parallel基本是透明的,改个启动参数就行,但跨卡通信得注意PCIe带宽,别指望4090之间能有NVLink那种速度。
说实话你这个场景我太懂了,之前我们内部跑7B也卡在24G上。别急着换卡,可以先试试把vLLM的gpu_memory_utilization调低点,配合--max-num-seqs限制并发,很多情况是显存碎片问题不是真不够。如果量化到int8还慢,直接上AWQ或GPTQ的4bit,配合vLLM的awq backend,速度比GGUF稳得多,而且算子完全兼容。多卡的话其实不用改代码,vLLM原生支持张量并行,设个--tensor-parallel-size 2就行,但注意得是同型号卡,你如果之后能再搞张4090就完美了。offload到CPU我试过,慢到怀疑人生,只适合推理单请求的场景,别抱太大希望。