最近在试着用LLaMA-7B做点微调后的推理优化,看到PyTorch 2.0的torch.compile宣传得很猛,说是能显著减少kernel launch开销。但我自己在A100上测了一下,同样是fp16推理,用inductor模式反而比eager模式慢了大概15%,而且显存占用还高了。是不是我哪里设置不对?还是说compile对动态shape(比如beam search里的变长序列)不友好?另外,看到有些项目在推vLLM或者TensorRT-LLM,是不是对这种生成式任务,现阶段压根就不该指望torch.compile?求有实战经验的大佬指点一下,别让我再瞎折腾了。
PyTorch2.0编译模式和大模型推理,真的能无脑加速吗?
全部回复
共 12 条torch.compile对动态shape确实不友好,vLLM那套continuous batching才是正解,别在inductor上耗了。
torch.compile对动态shape确实不友好,beam search场景不如直接上vLLM,省心多了。
生成式任务还是别折腾compile了,TensorRT-LLM那套才是正解。
torch.compile对动态shape确实不友好,beam search场景建议直接上vLLM,省心还快。
这情况太真实了,静态shape下inductor还行,生成式任务还是别折腾compile了。
torch.compile对动态shape确实不友好,inductor的图优化一碰上变长就露馅,这结果不冤。
生成式推理现阶段还是vLLM那套pagedAttention实在,compile留给静态shape场景吧。
torch.compile对动态shape确实不友好,生成式场景还是vLLM那套paged attention实在,别跟inductor较劲了。
torch.compile对动态shape确实是硬伤,beam search这种变长输入基本每次都要重新编译或者走fallback,开销全回来了。我试过把max_seq_len固定成padding到同样长度,inductor倒是能快一点,但显存直接多出好几个G,感觉得不偿失。
vLLM和TensorRT-LLM我最近也在看,它们主要赢在PagedAttention和静态图优化上,生成任务里连续请求的batch管理比compile那套实在多了。你不如直接试下vLLM,llama-7b fp16部署起来挺快的,改动也不大。
另外你A100上inductor慢15%是不是没开cudagraphs?有时候默认配置下kernel fusion效果不明显,还得手动调torch.compile的mode和dynamic参数。不过说实话,现阶段torch.compile更适合CNN或者固定shape的transformer,生成式推理真别死磕它。
torch.compile对动态shape确实不友好,beam search场景建议直接上vLLM,省心又提速。
torch.compile在LLM推理这块确实不是银弹,动态shape或者带beam search的变长输入会让inductor的graph break很频繁,优化反而变负优化,我试过把padding到固定长度能好点但显存又上去了。生成式任务现在走vLLM或者TensorRT-LLM是更务实的选择,毕竟它们针对KV cache和连续批处理做了专门优化。你那个15%的倒退我觉得不算异常,可能跟模型里某些自定义op没被捕获也有关系,可以先看看编译日志里有没有大量fallback。要是项目能切框架,建议别在torch.compile上死磕了,省下时间调调vLLM的调度参数收益更大。
说实话你这个问题问到点子上了,torch.compile真不是无脑加速的银弹,尤其对LLM这种生成任务。我自己的经验是,compile对静态shape、固定batch的CNN或者BERT类模型效果明显,但一旦碰到beam search这种动态序列,inductor的图捕获和重编译开销反而会吃掉收益,甚至像你看到的负优化。你那个慢15%我猜大概率是capture时对变长序列做了不必要的guard检查,或者kernel fusion没覆盖到attention里的因果mask操作,显存高也可能是因为编译时保留了额外workspace。现阶段如果追求极致吞吐,vLLM和TensorRT-LLM确实是更靠谱的方向,它们直接绕过了PyTorch的dispatch开销,还把paged attention和continuous batching揉进去了,这是compile目前做不到的。不过torch.compile也不是完全没用,你可以试试把beam search的序列长度pad到固定值,或者只对decoder里最耗时的linear层单独compile,其他部分保持eager,这样能减少重编译的抖动。另外注意下你用的CUDA版本和cuDNN是不是跟PyTorch 2.0匹配,之前我遇到过因为cuDNN版本旧导致inductor生成低效kernel的情况。总之别太迷信宣传,这种生成式任务,工程优化往往比编译器魔法重要多了。
torch.compile对静态shape的cnn或者bert这类任务确实有效,但生成式模型这种变长自回归场景,它的graph capture优势基本被dynamic shape抵消了,显存涨大概率是编译缓存和额外中间张量导致的。你试试把max_seq_len固定住,或者用reduce_overhead模式看能不能好点,但说实话vLLM那套paged attention才是正解,它的continuous batching直接绕开了kernel launch问题。TensorRT-LLM更激进,但部署成本高,如果只是微调实验,不如先看看flash-attention有没有装上,那个对长序列的收益比compile明显多了。
torch.compile那个东西吧,我跟你讲,真不是无脑上的,尤其生成式任务里动态shape一多,inductor的图优化经常被无效重编译拖垮,你看到慢15%太正常了。我自己试过llama-7b,beam search宽度一变化,compile的cache miss能把节省的kernel launch全吃回去,显存高是因为它额外保留了graph的中间buffer,这玩意儿对可变长度序列是真的不友好。
vLLM和TensorRT-LLM那边才是正解,人家把paged attention和continuous batching做到内核里了,跟torch.compile压根不是一个赛道。你现在A100上跑fp16推理,如果追求吞吐和低延迟,直接上vLLM,配好gpu-memory-utilization,效果立竿见影;TensorRT-LLM更狠但要折腾plan文件,对动态shape支持也有限。
不过话说回来,torch.compile也不是完全没用,你要是批处理固定shape、不做beam search,纯贪心解码,把max_seq_len定死,它还是能有点收益的,但收益幅度远没宣传的那么夸张。你不如先确认下是不是开了fullgraph=True,还有mode是不是选的reduce-overhead,那个对显存占用影响挺大。
另外你测的时候有没有把torch.backends.cudnn.benchmark设成False?有时候cudnn自动调优跟inductor的codegen会打架,反而拖慢。最后补一句,如果你只是微调后做离线批量推理,vLLM的开销主要在前端调度,数据量小的话可能感觉不出来,但一旦并发上来,差距就彻底拉开了。
torch.compile对动态shape确实不友好,beam search这种场景还是vLLM更实在。
生成式任务别折腾compile了,inductor优化静态batch还行,变长序列直接劝退。