最近在给公司做LLM推理优化,看到PyTorch2.0的torch.compile宣称能提升30%-40%性能,就试了试。本地benchmark确实快了,但部署到生产环境(T4 GPU,batch动态变化)后发现两个问题:一是首次编译时间太长,大概要十几秒,预热的warmup策略没找到好的实践;二是配合vLLM或TensorRT-LLM时,compile反而和这些框架的CUDA graph冲突,偶尔报显存碎片错误。想请教各位,你们在生产环境里真的会用torch.compile吗?还是说只用来做训练?如果是推理,有没有和vLLM搭配成功的案例?或者说干脆别折腾,直接换ONNX或TensorRT更省心?刚接触这块,有点迷茫,求指点。
PyTorch2.0的compile到底该不该用在推理服务里?
全部回复
共 42 条同感,compile在动态batch下收益不稳定,和vLLM抢显存太伤了,生产上还是TensorRT稳。
我们试过把compile只用在固定shape的短序列场景,其他走TRT,勉强能用但维护成本高。
说实话T4上遇到显存碎片和CUDA graph冲突太正常了,compile在动态shape场景下收益本来就大打折扣,尤其跟vLLM那种自己管显存池的框架叠一起,很容易互相踩脚。我这边生产环境基本放弃torch.compile做推理了,要么纯vLLM要么直接TensorRT,compile更多是训练或者小模型快速验证时用一下。你要是真想省那点延迟,不如先试试把batch pad到固定尺寸或者用torch.jit trace掉动态维度,比折腾compile稳定得多。
说实话我们团队也踩过这个坑,T4上动态batch加compile基本就是给自己找事,显存碎片那味儿太熟了。现在我们的做法是训练用compile,推理直接转TensorRT,省心且稳定,性能还比compile高一截。vLLM那边官方其实不太建议再套一层compile,你不如把精力放在调vLLM的量化参数和page size上,收益更直接。如果你非得用compile,试试固定batch size加上cudagraph的专用池,但维护成本确实高,不太值得。
说实话我试过一轮之后就把compile从推理链路里撤了,T4上那点提升抵不过动态batch带来的显存碎片风险。现在基本是训练用compile,推理直接走TensorRT,省心太多。vLLM那边官方文档也没推荐跟compile一起用,建议你别在这上面耗了。
说实话你这情况我太熟了,之前我们试过在A10上跑对话模型,torch.compile本地压测好看得不行,一上生产跟vLLM的paged attention一碰就原形毕露,CUDA graph那层直接打架,显存碎片跟你描述的一模一样。后来我们彻底放弃在推理链路里用compile,改成纯vLLM加自定义的batching策略,反而稳定多了。
我的看法是torch.compile最适合的还是训练和那种batch固定、shape固定的离线批处理场景,比如离线批量打分或者数据预处理那种。推理服务里动态shape是常态,T4上本来就吃紧,再叠加编译优化带来的额外内存开销,性价比真的不高。
至于ONNX或者TensorRT,我们试过TensorRT,优化上限确实高,但工程成本也高,模型迭代一次就得重新导一遍,小步快跑的时候特别痛苦。现在我们是vLLM兜底,实在需要极致性能的场景单独给TensorRT包装一个服务,不混着用。
有个小建议,如果你非想用compile,可以试试只对decoder里那几个最热的算子做局部编译,别整个模型都包进去,这样能减少和CUDA graph的冲突面,但warmup时间还是要靠离线预跑然后缓存编译结果,生产环境没法等那十几秒。
说实话我在生产环境试过一轮就放弃了,torch.compile在动态batch下收益很不稳定,T4上那点提升还不够填编译和显存碎片的坑。现在基本就是训练完直接转成TensorRT引擎,用vLLM的PagedAttention做服务,省心得多。你要是非要用compile,建议只锁静态shape,或者等官方把和CUDA graph的兼容性磨平再说。
生产环境还是别折腾compile了,跟vLLM抢graph真没必要,直接TensorRT省心得多。
我试过compile配动态batch,显存碎片直接炸,后来老老实实切回ONNX了。
这场景太真实了,动态batch下compile的收益真不够看,还是老老实实走TensorRT吧。
直接说结论:推理生产环境别碰compile,折腾半天不如把精力花在vLLM的配置调优上。
说实话你这个场景我太有共鸣了,T4上跑动态batch的LLM,torch.compile那点加速根本盖不住编译和内存碎片带来的运维成本。我自己的经验是,这玩意儿在训练和离线批量推理里香,但线上服务特别是跟vLLM抢显存的时候,基本属于给自己找不痛快。vLLM自己那套paged attention和CUDA graph已经优化得很透了,你再套一层compile,等于两个调度器在打架,报错还特别难查。我更倾向的做法是,如果模型结构固定,直接走TensorRT或者ONNX Runtime,虽然导出时也得折腾一遍,但至少稳定,而且T4这种老卡上TensorRT的算子融合收益比compile更靠谱。倒是想问下你试过把batch维度固定成几个档位,比如8/16/32,然后用torch.compile加dynamic=False吗?这样能避开重编译,但显存碎片问题估计还在。反正我个人现在线上主力是vLLM+TensorRT,compile只在调新模型结构时用来快速验证效果,生产环境真不敢押宝在它身上。
说实话我折腾过一轮最后还是换回TensorRT了,compile的收益在动态batch下真的不稳定,尤其T4这种卡上显存碎片问题太头疼。不过如果是静态shape且重推理的场景,compile配cudagraphs倒是能打,但生产环境哪有那么多理想情况。vLLM那边官方其实不太推荐叠compile,他们自己的paged attention已经做了不少算子融合,硬上反而负优化。建议你先用torch.profiler看看瓶颈到底在哪,别盲目迷信那个30%的benchmark数字,很多时候是memory bound而不是compute bound。
说实话我试了一圈最后还是回归TensorRT了,compile在动态shape场景下收益真没那么香,尤其是T4这种卡上显存本来就紧,跟vLLM抢资源的时候编译开销和碎片问题太糟心。你提到的warmup我倒是看有人用固定shape先跑几轮再切动态,但代码侵入性太强,维护成本高。如果模型结构相对稳定,ONNX加TensorRT的确定性比compile强太多了,至少不会半夜突然给你报个CUDA error。
说实话我们团队也踩过这个坑,T4上动态batch加torch.compile的收益真没benchmark那么玄乎,而且跟vLLM抢显存那段简直一模一样。后来我们干脆把compile只用在离线批量预处理那种shape固定的场景,在线推理全部走TensorRT,省心太多了。你要是非得跟vLLM配合,建议看看它的torch.compile后端是不是默认关的,我们最后是直接放弃warmup,用真流量跑两轮才缓过来。
我们这边试过类似路径,最后放弃了,torch.compile在动态shape场景下收益太不稳定,T4上首编译十几秒确实劝退。跟vLLM抢显存那会儿我们直接心态崩了,后来干脆推理全走TensorRT,虽然转换麻烦点但至少不会半夜报警。不过好奇你们有没有试过把compile限定在static shape的decode阶段?听说有人这么搞能避开大部分冲突。
说实话T4上折腾torch.compile性价比挺低的,动态batch下CUDA graph的recompile开销比节省的那点计算时间还肉疼。我们之前也踩过这个坑,最后干脆在vLLM外面包了一层,只对静态形状的decode阶段开了compile,prefill还是走原始路径。你要是主要跑LLM,建议直接上TensorRT,ONNX对动态shape支持也一般,省下的时间拿去调vLLM的调度参数更实在。
说实话我踩过一模一样的坑,T4上torch.compile的收益在动态batch下会被编译开销吃掉大半,尤其你们还叠了vLLM,等于两套图优化在打架。我们后来干脆把compile限制在静态shape的纯模型推理场景,比如batch固定为1或32的流式任务,这种情况收益还能稳定在20%左右,但一旦接上vLLM的pagedAttention就立刻关掉compile,让vLLM自己管CUDA graph,冲突反而少很多。至于ONNX和TensorRT,如果你只跑LLM生成,TensorRT的engine一旦build好确实省心,但T4上int8量化容易掉精度,需要花时间校准,而且版本迭代时重build的痛你也懂。我目前的生产方案是:训练和离线批量推理用compile,在线服务直接走vLLM原生路径,不碰compile,最多用torch.compile跑一下非LLM的小模型试试水。你们有没有试过把warmup拆成几步,先跑一遍小shape再跑真实shape,能稍微缓解首编译的卡顿,但根治不了。也想问问你们显存碎片是用cudaMallocAsync解决的,还是直接换框架了?
说实话我试过一轮下来感觉torch.compile更适合训练或者单模型推理,跟vLLM那套叠加确实容易打架,CUDA graph那层冲突基本无解。现在生产环境我直接放弃compile,要么用vLLM自带优化,要么对固定shape的模型走TensorRT,dynamic batch下省心太多。倒是想问问你试过把compile用在prefill阶段、decode阶段单独开吗?我们这边卡在显存碎片问题上一直没调通。
T4上动态batch就别折腾compile了,直接TensorRT省心,vLLM自己那套graph优化够用了。
说实话你遇到的这个问题我太有同感了,torch.compile在静态shape下确实香,但一上生产动态batch就原形毕露。我们之前在一个T4集群上试过,也是被那个首次编译的十几秒搞得血压飙升,后来直接放弃了,因为只要输入长度一变,它内部可能就要重新tune,跟vLLM的paged attention叠在一起简直就是灾难现场。我个人觉得compile现阶段更适合训练或者离线批量推理,在线服务里那点性能提升真不够折腾的,稳定性才是第一位的。你想跟vLLM配合,不如直接把它关掉,让vLLM自己管理CUDA graph,至少人家对显存碎片有专门的pooling策略。要是追求极致延迟,与其跟compile较劲,不如单独把关键算子用TensorRT手写plugin,或者干脆用ONNX Runtime加TensorRT EP,虽然前期工程量大点,但跑起来心里踏实。另外问一句,你试过把batch限制成固定几个档位,然后用torch.compile的dynamic参数指定min和max吗?我们当时没来得及试这个,你要是验证过可以分享一下结果。
生产环境还是别折腾compile了,跟vLLM抢graph调度纯属给自己挖坑,T4直接TensorRT省心得多。
生产环境还是别折腾compile了,跟vLLM抢资源真不值当,直接TensorRT省心。
T4这种卡上compile收益真没多大,还容易出幺蛾子,vLLM配TRT才是正经路子。