最近在折腾把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 条V100跑int4的6B理论上不该这么慢,你试试把max_seq_len调成和实际输入差不多大,别留太多余量,显存占用和计算量能降不少。另外flash attention在transformers里开起来很简单,几行代码的事,对长文本收益很明显。pytorch compile也可以试,但第一次跑会编译很久,后续速度提升大概一两倍。还有个思路,如果只是长文本总结,可以考虑用流式输出加缓存,把首token延迟降下来,体感会快很多。
试试开flash attention,再调大batch size,长文本任务能快不少。
你试过把max_seq_len调小点吗?2000tokens输入对6B来说压力不小,V100跑int4按理说不该这么慢,我怀疑是显存碎片化或者序列长度没限制住。flash attention在transformers里现在直接开就行,能快个30%左右,pytorch compile对GLM支持一般,容易踩坑。另外vLLM你要是装吐了,可以试试TGI,docker拉起来改个--max-input-tokens参数就完事,比vLLM省心不少。
你这情况我踩过坑,int4加载对长文本推理反而会慢,因为反量化开销不小。先试试直接fp16加载,V100显存跑6B完全够,速度能快不少。另外2000tokens输入建议把max_seq_len设到4096,避免padding浪费计算。flash attention值得装,能省个30%左右时间,pytorch compile对GLM支持一般,别抱太大期待。如果还慢,看看是不是没开CUDA graph,vLLM那套依赖确实麻烦,但装好后提升是质的飞跃。
试试把max_seq_len调小点,2000输入其实挺吃显存带宽的,长文本推理慢正常。
我最近也遇到过类似情况,int4加载反而可能因为反量化开销拖慢速度,试试直接fp16加载,V100的16G跑6B其实够用。另外长文本场景下,max_seq_len设成2048会强制做大量padding计算,改成动态padding或者直接截断到输入长度能快不少。flash attention在V100上支持有限,不如先试pytorch compile,我这边compile后推理快了将近一倍。vLLM那个依赖确实坑多,实在不行就用transformers的generate接口,把use_cache打开,batch size设1就好。
这问题我踩过,transformers加载int4本身就慢,尤其长文本场景,建议直接换vLLM,依赖报错多半是版本问题,Python 3.10加torch 2.1基本能过。vLLM里把max_model_len设到4096,gpu_memory_utilization调0.9,吞吐能顶你现在的十倍。另外flash attention在V100上其实开不了,pytorch compile对GLM支持也一般,别浪费时间。
V100跑int4的6B这个速度确实不太正常,我之前用A10跑同样配置大概1-2秒。你试试把max_seq_len设成2048,然后开一下torch.compile,能提升不少。另外长文本场景建议把输入切块处理,别一次性塞2000token进去,显存占用和计算效率都会好很多。vLLM那个先别折腾了,对量化模型支持一般。
V100跑int4的6B其实瓶颈多半不在显存,而是卡在transformers的decode阶段,单卡吞吐就那么点。你试下把max_seq_len设成和输入长度匹配,别留太大余量,能省点显存带宽。另外flash attention在V100上收益不大,但pytorch compile和torch2.0的静态图模式可以试试,我这边实测能快30%左右。vLLM报错大概率是CUDA版本或者pynvml没对齐,你可以看看是不是python3.8以下,换3.10或者3.11直接pip装预编译wheel会省事很多。长文本总结这种场景,要是能接受牺牲点精度,把输入分段推理再拼结果,体感延迟会低不少。
你这情况我上周刚踩过一模一样的坑,int4 + transformers慢是正常的,瓶颈基本在自回归的逐token生成上,2000tokens输入光prefill就得占不少时间。建议先试试把max_seq_len调小到输入长度+输出长度的1.2倍,别给默认的8192留太多冗余,batch size调成1就行。vLLM那边报错大概率是CUDA版本和flash-attn不匹配,实在不行就换transformers的modeling_chatglm.py里手动开torch.compile,配合use_flash_attention_2=True能快个40%左右。另外你输出100-200tokens的话,可以试试max_new_tokens而不是max_length,能省掉不少padding计算。
试试开torch.compile+flash attention,能快一半,另外int4加载时记得把device_map设成auto。
vLLM那个别折腾了,对6B这种小模型收益不大,先把max_seq_len调成和你输入输出匹配的数值。
这配置跑6B int4确实不该这么慢,我怀疑瓶颈在量化加载方式上。你试试直接用transformers的bitsandbytes加载,别用官方那个quantization,我上次换了下速度直接翻倍。另外长文本输入的话,max_seq_len别设太大,2000tokens输入配512输出就够了,batch size设1就行,重点检查下是不是被CPU offload拖累了,V100的显存带宽其实够用。flash attention值得装,PyTorch compile对推理提升不明显,主要还是看模型并行和算子优化。
试试flash attention吧,vLLM报错多半是版本问题,换个docker镜像能省不少事。
说真的,V100跑int4的6B不至于这么慢,3-5秒明显不对劲。你试试把transformers版本降到4.35左右,新版有些量化算子反而没优化好,我之前换回旧版直接快了一倍。另外你那个长文本场景,2000tokens输入对显存带宽压力不小,建议把max_seq_len调到刚好够用就行,别留太多余量,不然KV cache会白白吃资源。flash attention肯定要开,V100虽然不支持flash-attn 2的某些优化,但至少能省点显存带宽。pytorch compile也值得试,不过记得把mode设成reduce-overhead,我第一次用默认模式反而更慢。还有个偏方,你试试把quantization改成bitsandbytes的8bit,有时候比int4在V100上更快,因为int4的dequantize在旧架构上开销更大。最后,vLLM别折腾了,它对V100的兼容性确实一般,官方文档都写着要Ampere以上才推荐。你先把这些试一遍,要是还慢,咱们再讨论是不是数据并行或者CPU瓶颈的问题。
试试flash attention吧,你这输入长度上去了收益挺明显的,vLLM可以先放放。
试试把max_seq_len调到和你输入输出差不多,再开flash attention,速度能翻倍。
试试FlashAttention吧,int4加载本来就没吃满显存,瓶颈在解码速度。另外batch size调1,max_seq_len别超2048,长文本提速明显。
V100跑int4的6B其实瓶颈多半不在显存,transformers原生推理本来就没优化到位。你试试把torch.compile开起来,配合flash attention 2,单次延迟应该能砍掉一半。另外长文本场景max_seq_len别拉太高,2000输入其实可以分段处理,vLLM报错大概率是CUDA版本和pytorch不匹配,换个docker镜像可能省事很多。
你提到的batch size在单卡单请求场景基本没用,真正影响速度的是KV cache的复用和显存带宽。我建议先装个text-generation-inference框架,参数直接用默认,它内部做了连续批处理和算子融合,比手调transformers稳得多。要是还慢,检查下CPU内存是否被swap拖累,V100的PCIe带宽有时候是隐藏瓶颈。
直觉是你这个延迟主要卡在长文本的prefill阶段,2000tokens输入用int4量化反而可能更慢,因为反量化有额外开销。可以试试直接加载fp16不量化,V100显存刚好够用,速度可能反而更快。另外flash attention在V100上效果有限,因为它是Ampere架构才完全支持,不如先试试把max_seq_len限制在2048看看,有时候默认配置会预留太多余量导致显存碎片化。vLLM如果实在搞不定,可以看看transformers的bettertransformer接口,一行代码就能开启,对解码速度提升挺明显的。
你这情况我上周刚踩过坑,int4加载方式本身没问题,但transformers的generate默认用贪心搜索,长文本输入下prefill阶段特别吃算力,你先试试把max_new_tokens调小看单token延迟是否正常。另外vLLM装不上就别死磕了,直接上flash-attention,V100虽然不支持fa2但fa1能跑,配合torch.compile能压到1.5秒左右。还有个冷门技巧,把输入切段做流式总结,比一次性塞2000tokens快得多。