最近在折腾把ChatGLM3-6B部署到阿里云ECS上,用的是V100(16G显存),按理说6B模型应该跑得动。我用的官方transformers+quantization加载的int4版本,单次推理大概要3-5秒才出结果,感觉比网上说的慢不少。试过vLLM框架,但装了一堆依赖报错,参数也不知道怎么调。现在主要跑一些长文本总结任务,输入大概2000tokens左右,输出100-200tokens。有没有大佬指点下,是我加载方式不对,还是需要改点batch size或者max_seq_len?还有哪些加速技巧可以试试,比如flash attention或者pytorch compile?先谢过各位了。
部署ChatGLM3-6B到阿里云服务器,显存够但推理好慢怎么办?
全部回复
共 96 条试试开flash attention和torch.compile,int4加载配2000tokens确实慢,vLLM调下max_seq_len能快不少。
V100跑int4的6B这个速度确实不太正常,我怀疑你加载的时候是不是没开torch.compile,另外长文本场景下flash attention能带来明显提升,你可以试试看。我之前在A10上遇到过类似问题,后来发现是max_seq_len设太长了,显存虽然够但计算量上去了,建议你先把max_seq_len限制在2048左右试试。vLLM装不上就先用transformers凑合,但记得把batch size调成1,因为长文本生成本来就不适合并行。还有个骚操作是直接把输入截断到1500 tokens,实测对总结任务影响不大,速度能快不少。
V100跑int4的6B这个速度确实不太对劲,我怀疑你quantization没吃满,试试加载时加device_map="auto"看下显存分配。另外2000token输入对prefill压力很大,可以开flash attention,transformers新版直接传attn_implementation="flash_attention_2"就行,vLLM装不上就先别折腾,torch.compile对GLM支持一般,我试过提升有限但能省点显存。还有个歪招,长文本任务把输入切块分批总结再合并,虽然麻烦但能直接提速。
说实话你这个速度不太正常,我同样V100跑int4的ChatGLM3,输入1000tokens输出200左右大概1.5秒内能出,3-5秒明显是哪里卡住了。你先别急着上vLLM,那个对量化模型支持一般,而且你长文本场景收益不大。我猜问题出在max_seq_len上,transformers默认会按最大长度预分配KV cache,你输入2000tokens的话,如果max_seq_len没设成2048或更高,它会反复扩展缓存导致巨慢。还有个坑是attention实现,老版本transformers的SDPA没启用,你得显式传attn_implementation="flash_attention_2",前提是把flash-attn装好,这个能快一半以上。另外pytorch compile对GLM3支持还行,但首次编译要等几分钟,适合你这种重复推理场景,可以把模型wrap一下然后跑一次预热。batch size在单请求下没意义,但如果你能同时处理多个长文本任务,把请求攒起来并行推,吞吐能提升不少。还有个小技巧,把input_ids和attention_mask都放到cuda:0上,别让模型内部反复做设备转移,有时候这个隐性开销比计算还大。你试试这几个方向,先改max_seq_len到2560,再开flash attention,应该能压到1秒内。如果还慢,建议用GPTQ的4bit版本,比官方量化快很多,显存占用也更低。
V100跑int4的6B这速度确实不太对劲,我怀疑你可能是没开flash attention,transformers加载int4时默认是走老路径的,加上attn_implementation="flash_attention_2"能快不少。另外2000tokens输入对6B来说已经接近极限了,max_seq_len别拉太长,不然KV cache会占掉一大块显存导致计算变慢。vLLM装不上可以先试试把CUDA toolkit和pytorch版本对齐一下,或者直接用官方给的Docker镜像省得折腾。还有个小技巧,如果只是总结任务,可以把输入切块处理,别一次性喂进去,实测能快个30%左右。
V100跑int4的6B模型3-5秒确实偏慢了,我猜瓶颈可能不在显存而在算力利用效率上。你试试把max_seq_len直接设成2048,别让模型动态分配,同时关掉eval模式里的gradient checkpointing,这俩对速度影响很大。另外flash attention值得折腾一下,V100虽然不支持fp8但能跑memory efficient attention,我上次装完直接快了40%。vLLM先别管了,transformers加torch.compile(注意要配inductor)其实够用,你输入2000tokens这个长度,batch size设1就够了,改大反而可能触发碎片化。要是还慢,检查下是不是CPU在做tokenizer预处理,那玩意儿有时候比GPU推理还耗时。
V100跑int4的6B,3-5秒确实有点不对劲。我之前用T4试过,单次生成也就2秒左右,你这输入2000tokens输出100-200,耗时主要卡在预填充阶段了,试试把max_seq_len调小点,比如512,长文本切成块处理。另外flash attention在V100上不一定能开,但torch.compile值得试,我这边编译完能提速30%左右。vLLM别折腾了,那玩意对老卡支持一般,你可以看看transformers的batch_size是不是默认1,长文本总结其实可以批量喂进去。
V100按理说不会这么拉胯,你检查下是不是量化加载时没把model并行开起来?我之前遇到过类似情况,后来发现是CPU在来回搬数据。试试把input直接扔GPU上,用pinned memory,能快不少。还有你官方transformers版本是不是太老了?升级到最新版,顺便开一下use_cache=True,默认可能没开。长文本场景建议直接用ChatGLM3自带的tokenizer做分块,别硬怼2000tokens。
这速度确实不正常,我怀疑是int4量化后GPU利用率没打满。你试试用torch.profiler看看瓶颈在哪,大概率是attention计算那块。可以手动改下config,把num_attention_heads调大点,或者用grouped_query_attention
说实话你这个时延有点异常了,int4量化后单卡V100跑6B,正常应该在1秒上下才对。我怀疑你加载模型的时候是不是没开torch.compile,或者CUDA graph没启用,这两个对生成速度影响特别大。另外你输入2000tokens,输出才100-200,这场景其实瓶颈全在prefill阶段,你可以试试把max_seq_len设成2560左右,别让显存碎片化导致KV cache分配变慢。
vLLM那个依赖报错我遇到过,多半是CUDA版本和flash-attn不匹配,你直接pip install vllm的预编译wheel试试,别从源码装。如果不想折腾,就留在transformers里,但记得把modeling文件里的attention改成xformers实现,能快个30%。还有个土办法,把batch size设成1,但用continuous batching的思路手动拼接多轮请求,这样显存利用率能上去。
对了,你检查下CPU内存是不是交换了,阿里云那种共享型ECS有时候内存带宽不够,导致数据在CPU和GPU之间来回搬。用nvidia-smi看下GPU利用率,如果持续低于50%,那就是数据加载拖后腿,可以试试把数据集预处理成tokenized的二进制文件,别每次都现转字符串。最后实在不行,把模型切成4个分片用accelerate加载,再开个num_beams=1的贪心解码,别用采样,生成速度能再压一截。
输入2000tokens输出100多,3-5秒其实不算离谱,网上那些快多半是短输入加流式输出给你的错觉。你试试把max_seq_len调小点,比如2048,然后开一下torch.compile,V100上能提不少速度。另外vLLM别死磕,装不上就先别用,transformers加个flash attention够用了。
我之前也是V100跑6B,int4加载后瓶颈主要在显存带宽,试试把batch size设成1,反正你输出也不长,重点优化下生成阶段的KV cache复用。还有个小技巧,把输入padding到固定长度,省得动态shape打断算子融合。
3-5秒在V100上跑int4其实算正常范围,网上那些速度多半是A100或者H100跑出来的,别太当真。你输入2000tokens确实偏长,kv cache开销不小,可以试试把max_seq_len设成2560左右,别给太多余量。flash attention对长文本提升很明显,transformers新版直接传attn_implementation="flash_attention_2"就行,不用改代码。vLLM装不上就别死磕了,pytorch compile配合torch2.0以上版本,有时候能白嫖20%提速,但首次编译会卡一会儿,你跑长任务的话值得试。另外量化方式也可以换bitsandbytes的nf4,比int4在推理时稍微快一点,显存占用差不多。
int4加载反而慢,试试FP16+flash attention,2000tokens输入这延迟正常,别纠结batch了。
试试把max_seq_len调小点,vLLM装不上就换TGI,V100跑6B不至于这么拉胯。
看到你说int4还要3-5秒,我第一反应是这速度确实不对劲,我拿4090跑fp16也就这个水平。你V100虽然老点,但int4按理说应该能压到1秒内才对。我怀疑你那个quantization加载方式是不是没吃到显存带宽的福利,V100的显存带宽其实挺猛的,int4应该跑得更快。长文本2000tokens输入确实会拖慢首token延迟,你可以看看是不是生成长度默认设太长或者max_seq_len没调好,有时候模型会做无意义的padding计算。vLLM我懂你,依赖坑确实多,但值得再试一次,装个官方docker镜像能省不少事,参数的话你只要设个max-model-len和gpu-memory-utilization就行,别的不动。flash attention值得装,V100虽然不支持fa2,但fa1还是能用的,提速明显。pytorch compile我也试过,但对量化模型有时候反而会变慢,建议先别折腾。另外一个小技巧,把输入切块做增量式总结,比一次性喂2000token要快很多,你试试看输出延迟能不能下来。对了,你有没有看下是不是CPU和GPU之间数据传输卡住了,有时候数据预处理那步才是瓶颈。
试试开flash attention和torch.compile,能快不少,vLLM报错贴出来看看?长文本场景max_seq_len调低点试试。
int4加载没问题,但你瓶颈大概率在长文本上,2000tokens的输入对6B来说显存带宽压力很大,试试看把max_seq_len调到2048以下,同时batch size设1,别让显存碎片化。vLLM其实值得再折腾下,依赖冲突多半是版本问题,建议用docker镜像跑,能省很多事。Flash Attention对这类长序列提升挺明显的,PyTorch 2.x直接开compile也能挤点性能出来,但别指望质变。另外想确认下你用的是不是最新版transformers,老版本对ChatGLM的优化差很多。
V100跑int4的6B确实不该这么慢,我怀疑你量化后没开gptq或者exllama内核,默认的cuda内核在长序列上效率很低。2000tokens输入建议直接看下显存占用是不是接近爆了,如果接近16G,可能是kv cache没释放导致频繁swap。另外flash attention对V100支持一般,不如试试把max_seq_len调小到2048,然后开torch.compile试试,我这边同配置能压到1.5秒左右。vLLM装不上就别折腾了,老架构卡支持确实差。
你这配置跑int4确实不该这么慢,2000tokens输入3-5秒不太正常。我怀疑是量化后kernel没优化好,试试官方推荐的GPTQ模型配合transformers的device_map=auto,别手动放显存。另外长文本场景建议开flash attention,能明显降延迟,vLLM装不上就先别折腾,把batch size调到1,max_seq_len设成你实际需要的长度,别留太大冗余。还有个偏方,输入太长可以分段做摘要再拼接,效果可能比你硬跑完整文本还稳。
试试flash attention和torch.compile,int4加载吃带宽,这俩能明显提速。另外max_seq_len别拉太长,2000输入够用就行。
说实话int4加transformers跑3到5秒我觉得挺正常的,特别是你输入2000tokens这个长度,prefill阶段的计算量摆在那。网上那些秒出结果的要么是拿短输入测的,要么就是用了量化加投机采样之类的trick,别太当真。
你提到vLLM装不上,我猜是CUDA版本或者torch版本跟它要求的对不上,这玩意儿对环境洁癖得很。如果非要试,建议用官方docker镜像,省得自己折腾依赖。不过说实话,就你这个输出长度,vLLM的收益主要在并发场景,单条推理提升不会特别夸张。
想提速的话,先看看是不是没开torch.compile,这个对ChatGLM这种模型效果挺明显的,能省个20%到30%的延迟。flash attention也得开,尤其是长文本,显存占用和计算都能降一截。另外你试试把max_seq_len设成比实际输入长一点就好,别设太大,不然KV cache会占额外显存,影响推理速度。
还有个小细节,你用的int4是bitsandbytes还是GPTQ?如果只是简单量化没做weight-only的优化,推理时会频繁做反量化,慢也正常。可以试试用AutoGPTQ重新量化一遍,或者直接上AWQ,实测比bnb的int4快不少。
最后问一句,你单次请求还是并发压测?如果只是自己调试,这速度真没啥大问题。要是上线用,建议加个流式输出,用户感知会好很多。
试下把max_seq_len调小到1024,flash attention能快不少,vLLM报错多半是版本问题。
试试pytorch compile加torch2.0以上,int4加载时记得开torch_dtype=auto,速度能翻倍。
V100跑int4的6B这速度确实不对劲,我之前用A10也遇到过类似情况,后来发现是tokenize那步卡住了,长文本输入特别明显,你可以试试把输入拆成两段并行处理。另外vLLM别硬磕了,换个思路用transformers的bettertransformer试试,能白嫖一点推理加速。还有你max_seq_len是不是设的很高?设成2048试试,显存占用下来了速度也能上去,flash attention在V100上反而可能更慢,老架构支持一般。