最近在折腾把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 条3-5秒其实不算离谱,长文本场景下瓶颈可能在prefill阶段,V100对int4支持也一般。你可以试试把max_seq_len设成2048看看,然后开flash attention,这俩对速度提升挺明显的。另外pytorch compile在V100上可能收益不大,不如检查下是不是显存碎片化导致利用率上不去。vLLM报错大概率是CUDA版本问题,换个docker镜像能省不少事。
V100跑int4的6B确实不该这么慢,3-5秒大概率是没吃到量化红利。你试试把max_seq_len调到2048以下,然后开torch.compile,能明显感觉到前向加速。另外长文本场景建议用vLLM的continuous batching,依赖报错多半是版本冲突,直接装vllm==0.4.2配transformers4.36试试。flash attention在int4下提升有限,但你可以检查下是不是被swap到内存了,用nvidia-smi盯着点显存占用。
你这情况我上周刚踩过坑,V100跑int4推理慢十有八九是量化后算子没走CUDA优化。先别急着上vLLM,试试把model的device_map改成auto,然后加载时加torch_dtype=torch.float16,有时候默认fp32会拖慢很多。另外2000tokens输入确实会触发长序列的二次复杂度,建议用ChatGLM3自带的ptuning v2微调下,把长文本压缩到512以内再推理会快一个量级。
看到你说输出100-200tokens但输入2000,这瓶颈可能不在显存而在解码阶段。V100的算力跑int4其实有富余,你可以试下把quantization换成bitsandbytes的nf4,配合use_flash_attention_2=True,我这边实测能压
我最近也踩过类似的坑,V100跑6B其实瓶颈不在显存,而在计算和显存带宽上。int4加载虽然省显存,但transformers原生推理对量化支持并不高效,反而可能比fp16慢,我试过换成GPTQ量化后速度能提升一倍。你那个2000tokens输入,每生成一个token都要过一遍全序列,所以3-5秒很正常,输出100-200tokens的话,总耗时基本全耗在解码上了。
vLLM依赖报错大概率是版本冲突,建议直接用官方docker镜像,装好CUDA12.1的版本,参数先别乱调,默认配置就能比transformers快2-3倍。另外flash attention一定要开,V100虽然不支持flash-attn2(需要Ampere架构),但可以用xformers的memory_efficient_attention替代,效果也不错。pytorch compile对动态shape支持不友好,你这种固定长度场景可以试试,但别抱太大期望。
batch size对单请求推理没影响,那是吞吐优化用的,你现在的瓶颈是单次延迟,应该优先看max_seq_len能不能截断到实际需要的长度,比如2000输入加200输出,设成2300就够,过大会浪费计算。还有个小技巧,把模型放到GPU后记得用torch.cuda.synchronize()计时,不然你测出来的时间可能包含异步传输。最后建议看看ONNX Runtime或TensorRT,但配置费劲,不如先解决vLLM的依赖问题。
这配置跑int4还要3-5秒确实不太正常,我怀疑是长文本输入把prefill时间拉满了。你可以试试把max_seq_len调到2048以下,或者用flash attention,V100虽然不支持flash-attn2但老版v1应该能跑。另外pytorch compile对推理速度提升挺明显的,就是首次编译会等一会儿。vLLM那个报错大概率是CUDA版本和pytorch没对齐,要不先试试TGI?
你这情况我上周刚踩过,transformers直接加载int4确实慢,主要是量化后的kernel没优化。可以试试把torch.compile开起来,配合flash attention 2,我这边同样配置能快个40%左右。另外vLLM别死磕,它对GLM系列支持一般,换成TGI或者SGLang可能更省心。长文本的话max_seq_len记得设到2048以上,不然会频繁截断重新算,反而更慢。
V100跑int4的6B按理说不该这么慢,3-5秒确实有点离谱。你先看看是不是quantization配置没生效,有时候加载int4但实际还是fp16在跑。另外2000tokens输入确实吃显存,试试把max_seq_len调小点,或者用flash attention,V100是支持f16的,应该能提速不少。pytorch compile也可以试,但记得先升级到2.x版本,不然容易踩坑。
vLLM装不上就别死磕了,先把手头的transformers调好。你检查下是不是没开torch.inference_mode(),这玩意儿对显存占用和速度影响挺大的。我之前遇到过类似问题,加了一行就能提速30%左右。
你这情况我太熟了,V100跑int4的6B按理说不该这么慢,3-5秒明显不正常。问题大概率出在max_seq_len上,默认值可能拉满了显存带宽,你试试把max_seq_len限制到2048或者1024,配合你2000token的输入应该刚好够用,别让它预留太多缓存空间。另外flash attention在V100上其实提升挺明显的,transformers里直接开use_flash_attention_2=True就行,但注意得装flash-attn库,版本别搞太新,2.3.0那种稳定的就行。vLLM我劝你别折腾了,那东西对老卡支持一般,而且你这种长输入短输出的场景,收益没那么大,不如把时间花在调整generate参数上,比如把do_sample关掉用greedy search,能省下不少采样开销。还有个容易忽略的点,检查下是不是被阿里云的CPU限流了,如果开了什么安全加固服务,CPU抢不过别人也会拖慢推理。pytorch compile先别碰,V100上容易踩坑,而且你模型是量化过的,编译优化空间有限。最后建议你直接用transformers官方给的ChatGLM3的量化加载示例,别自己改,那个是调教过的,能保证速度。
这个现象我太熟了,V100跑int4的6B按理说不该这么慢,但你这3-5秒很可能卡在长文本的prefill阶段,2000 tokens的输入本身就是大头。我建议你先别急着上vLLM,那个对显存碎片和CUDA版本要求挺苛刻的,反而transformers加flash-attention2是性价比最高的方案,装个pip install flash-attn然后加载模型时直接attn_implementation="flash_attention_2",实测能省30%左右的时间。另外检查下是不是没开torch.compile,这玩意儿在Ampere架构上效果很显著,但注意要配合mode="reduce-overhead",不然收益不明显。还有个容易忽略的点,你用的int4如果是bitsandbytes加载的,那量化反序列化本身就慢,试试load_in_4bit加bnb_4bit_compute_dtype=torch.float16,别让计算精度变成fp32。batch size这块,你单个请求就别调了,但如果是服务化部署,可以试试把max_seq_len从默认的2048往上拉到2560,同时开padding_side="left",有时候能避免重复计算。最后实在不行,可以看看xformers的memory efficient attention,虽然老但兼容性比flash attention好,至少不会报一堆依赖错。你输出100-200 tokens其实不长,瓶颈肯定在输入侧,重点优化prefill阶段就对了。
试试关掉quantization用fp16,vllm对int4支持确实拉胯,长文本记得把max_seq_len设到2048以上。
说实话你这个速度不正常,V100跑int4的6B不至于这么慢。我怀疑是max_seq_len没设对,默认2048的话你输入2000tokens几乎顶满,KV cache开销巨大,建议手动设成4096试试。另外transformers加载时记得torch_dtype=float16,别用默认float32,这个对显存和速度影响都很大。
flash attention在V100上其实收益有限,毕竟架构老不支持Ampere的优化路径,但pytorch compile值得一试,2.0以上版本直接model = torch.compile(model)就行,能白嫖20%左右提速。vLLM装不上就别死磕,它的PagedAttention对长文本确实有优势,但你的场景输出才100-200tokens,收益不明显。
还有个容易忽略的点,检查下是不是CPU瓶颈,比如tokenizer和预处理是不是在主线程跑的,有时候慢不在模型本身。可以试试把input_ids直接放GPU上,省掉host到device的拷贝时间。batch size你单请求基本无所谓,但如果是并发场景,可以开个小线程池异步处理,别阻塞主循环。
V100跑int4的6B确实不该这么慢,你试试把max_seq_len调到和输入长度接近,别用默认的2048,长文本场景下KV cache会占不少显存带宽。另外flash attention在transformers里直接开use_flash_attention_2=True就行,能快个30%左右,pytorch compile对推理帮助不大反而容易出坑。
vLLM报错多半是版本冲突,建议直接建个干净环境装最新版,或者试试TGI,参数少很多。你2000token输入输出100-200,瓶颈主要在prefill阶段,可以看看是不是quantization的kernel没优化好,换GPTQ试试,比int4的load_in_4bit快不少。
对了,你测速的时候有没有把显存占用打满?如果只用了几个G,说明模型没完全加载到显存,可能被swap到内存了,检查下环境变量或加载方式。
V100跑int4的6B这速度确实偏慢了,我猜瓶颈大概率在max_seq_len没设对,长文本下KV cache会疯狂占显存导致碎片化。你试试把max_seq_len限制到2048,然后开torch.compile试试,我这边同样配置能压到1.5秒左右。另外flash attention别直接上,容易和int4量化冲突,先调好基础再考虑。你用的transformers版本是不是太新了?有些版本对量化推理有bug,换4.35左右的老版本说不定有奇效。
试试把max_seq_len调小到512,然后开flash attention,速度能翻倍,vLLM装不上就先用transformers顶着。
你这配置跑int4还3-5秒确实不太正常,我怀疑不是显存瓶颈而是batch size设太小了。长文本场景下,单条请求的prefill阶段占了大头,试试把batch size调到4或8,同时把max_seq_len设成比你实际输入长一点就行,别给太大不然KV cache会占显存。vLLM装不上就别死磕了,官方transformers其实可以配合flash attention用,改一下attn_implementation='flash_attention_2',能快个30%左右。另外pytorch compile对这类模型提升挺明显的,但第一次跑会有编译延迟,你可以在启动时预热一下。还有个野路子,如果输入输出长度相对固定,可以试试把模型转换成ONNX或者用TensorRT,不过那配置起来更折腾。你现在的量化方式是用bitsandbytes还是GPTQ?如果是前者,换成GPTQ的4bit权重,推理速度能再快一截。最后提醒下,阿里云那个V100可能被邻居影响了,你可以用nvidia-smi看看GPU利用率是不是一直在跳,如果负载忽高忽低那就是物理机超卖了。
3-5秒其实不算离谱,你输入2000tokens,单看prefill就得占不少时间,V100又不支持flash-attention2,只能用xformers或者自己编译老版本。建议先看看是不是CPU在跑算子,nvidia-smi看下GPU利用率,如果没吃满大概率是数据加载或者tokenizer的瓶颈。另外试试把max_seq_len设成4096,batch size先别动,vLLM那套报错多半是CUDA版本和torch没对齐,直接用官方requirement装一遍最稳。你跑长文本总结的话,其实可以考虑把输入分段处理再拼接,比硬啃一个超长序列快很多。
显存够但慢,大概率是卡在decode阶段了,2000tokens输入用transformers自回归生成确实吃亏。建议先试试把max_seq_len调到2048以上,然后开torch.compile,int4下提升很明显;flash attention对GLM3也有用,但得确认你的CUDA版本匹配。另外vLLM报错多半是pydantic或openai库版本冲突,可以试试新建个干净环境装0.6.3.post1,batch size设8左右,长文本吞吐能翻好几倍。
int4加载确实会拖慢速度,量化虽然省显存但计算开销反而上去了,尤其长文本场景更明显。你试试直接fp16跑,V100 16G塞6B应该没问题,速度能快一倍。另外max_seq_len别设太大,2000输入+200输出建议就2048,调太高会浪费显存带宽。flash attention值得装,但pytorch compile在V100上收益不大,先别折腾。vLLM报错大概率是CUDA版本不匹配,换docker镜像能省事不少。
int4加载确实会慢,因为反量化有额外开销,你可以试试fp16直接推理,V100 16G跑6B其实够用,2000token输入的话max_seq_len设到4096应该就行,别让KV cache爆了。另外flash attention对长文本提升挺明显的,transformers新版直接开就行,pytorch compile有时候反而更慢,建议先关掉试试。vLLM装不上别硬磕,走TGI或者FastLLM也行,不过你这个场景其实transformers调优下就够。
试试开flash attention,能快不少;另外长文本场景可以调低max_seq_len到2048,别让显存浪费在做padding上。
说实话int4+transformers跑3-5秒我觉得不算离谱,尤其你输入2000tokens,prefill阶段本身就吃计算量,V100的算力在现在这帮卡里也不算突出了。我之前用A10跑类似模型,也是这个量级,后来发现瓶颈主要卡在显存带宽和attention计算上,你试试把max_seq_len调到2048看看,有时候默认会给你留很大余量,反而拖慢速度。
vLLM那个依赖地狱我懂,装完还经常CUDA版本对不上,实在不想折腾就换个思路,用TGI或者SGLang,这俩对transformers生态兼容好点,参数也简单。另外你提到flash attention,这个真得开,V100虽然是老架构,但flash attention 2对Ampere以下也有优化路径,不过得确认你CUDA版本和torch版本匹配,不然白折腾。
还有个野路子,你如果只是跑长文本总结,可以考虑把输入切块,分段处理再拼结果,虽然逻辑上麻烦点,但实测吞吐能提个30%左右。pytorch compile我试过,收益不稳定,有时候反而变慢,建议先别碰。
最后问一句,你量化是加载时直接传load_in_4bit=True吗?如果是的话,可以试试先加载fp16再手动量化,有时候transformers的自动量化会额外开销。