最近在调一个nlp分类模型,数据量不大(大概2万条),单卡3090训练。试了torch.compile,用默认模式跑,第一轮确实慢(编译开销),但后面几个epoch速度只提升了10%左右,和官方宣传的“训练提速30%-50%”差很多。而且用动态shape(比如变长序列padding到不同长度)直接报错,回退到eager模式。想问问大家:是不是小模型小数据量根本没必要上compile?还是我哪里设置不对?有一说一,模型里用了transformers的BertForSequenceClassification,加了个自定义分类头。有没有类似场景的老哥分享下实际收益?现在纠结要不要为了部署时的推理加速去折腾这个。
PyTorch 2.0的compile到底值不值得用?静态图加速不明显还报错
全部回复
共 88 条2w条数据真没必要折腾compile,transformers模型瓶颈在数据加载和GPU利用率,先把batch和梯度累积调好更实在。
同款transformers+自定义头,数据量也差不多。我试下来compile在小模型上收益确实有限,主要瓶颈在数据加载和GPU利用率上,建议先看看nvidia-smi是不是喂满。动态shape那个坑我也踩过,后来固定max_len加padding反而省心。如果你主要图部署时的推理加速,不如直接上ONNX或者TensorRT,训练阶段别折腾compile了。
torch.compile对你这场景确实容易拉胯,BERT加自定义头本来就偏动态,padding长度一变它就得重新做图优化,编译开销全浪费了。我试过类似任务,反而用max_length固定+静态shape,compile能到15%左右,但也没宣传那么神。小数据量真没必要折腾,3090单卡跑2万条,eager模式也就多睡两觉的事。你现在纠结部署推理的话,不如直接上ONNX或者TensorRT,那个收益才是实打实的。
这场景跟我一模一样,小模型真没必要折腾compile,动态shape直接劝退,收益还不如多调两个epoch。
你这情况太正常了,2万条数据对3090来说就是小case,计算密度不够,compile的图优化收益全被内存搬运和Python开销吃掉了,10%已经算不错了。动态shape报错是老毛病了,transformers里那些position_ids和attention_mask的维度变化,compile目前确实搞不定,只能等官方慢慢优化。我自己的经验是,小模型别折腾compile,把精力放在gradient accumulation和混合精度上,收益来得更直接。倒是你提到的部署推理,如果服务端要跑大量请求,静态shape+compile能省不少显存和延迟,这个场景反而值得投入。
小模型上compile收益确实有限,动态shape直接劝退,我试过几次也老实回eager了。
你这种情况不如把精力放在优化数据加载和混合精度上,部署时再考虑导出onnx或tensorrt。
小模型真没必要折腾compile,你这收益正常,动态shape目前就是硬伤,直接eager吧。
跟你差不多,小模型上compile纯属给自己找事,收益低还折腾,部署直接上onnx或者torchscript更省心。
2万条数据上3090,这规模本身训练就几分钟一个epoch,compile那点收益基本被开销吃掉了,正常。动态shape报错太真实了,我试过给bert加mask,padding一长一短直接炸,后来干脆只在固定batchsize下用。你那个10%提升其实不算差,官方30-50%都是大模型大batch堆出来的,小数据真没必要折腾。部署推理的话,建议直接上onnx或者tensorrt,比compile稳得多,收益也大。
你这场景跟我之前跑bert-base做意图分类几乎一模一样,2万条数据上compile的收益确实就这水平,官方benchmark都是大模型大batch堆出来的。动态shape报错太正常了,torch.compile对变长序列的支持目前就是玄学,我后来直接固定max_len+cache_padding,提速才勉强到20%。小模型真没必要折腾这玩意,部署时用ONNX或者TensorRT反而省心,收益还更稳定。
小模型上compile收益确实有限,动态shape是硬伤,建议先试下max_length固定+padding,能省不少心。
推理阶段用onnx或者TensorRT更实在,别在compile上死磕了。
说实话你这个场景我太熟了,之前用bert+自定义head跑金融文本分类,数据量跟你差不多,compile收益也就在8%-12%晃悠。我觉得官方那个30%-50%的benchmark大概率是拿大模型、大batch、静态shape堆出来的,小数据量下编译开销摊不平,计算密度又不够,提速自然上不去。动态shape报错这个真没辙,torch.compile对变长序列的支持一直很迷,我后来干脆统一max_len+attention mask,虽然多算点padding但至少能稳定跑compile。不过你要是纠结部署时的推理加速,我觉得更值得把精力放在onnxruntime或者tensorRT上,3090上fp16+trt的bert推理提升能到2-3倍,比compile香多了。训练阶段省那10%时间真不如换个思路,比如试试gradient accumulation调大batch,或者用adamw8bit省显存换更大batch,收益可能更明显。另外你可以检查下自定义分类头里有没有什么动态操作,比如python控制流或者tensor.shape直接参与计算,这些都会触发graph break,导致部分代码回退eager,实际提速就被稀释了。反正我的结论是,小模型小数据量,compile属于锦上添花,不是雪中送炭,别太抱期望。
同款配置,bert+自定义头,2w数据量差不多也就这个收益,10%算正常。官方那个30%-50%是拿大模型大batch堆出来的,小数据量编译开销占比太高,感知不强。动态shape就别指望了,compile目前对变长序列支持就是渣,直接关掉省心。你要想部署提速,不如转onnx或者上tensorrt,比在这折腾compile实在。
我试过类似场景,动态shape直接劝退,小模型硬上compile纯属找罪受,省那点时间不够排查报错的。
说实话你这个场景我试过类似的,2万条数据上compile确实没啥甜头,编译开销摊不平,收益基本被吃掉了。动态shape报错太正常了,torch.compile对变长序列的支持现在还是半残状态,我后来干脆固定max_len+padding,勉强能跑但收益也就15%左右。你要是主要为了部署推理,不如直接上ONNX或者TensorRT,那玩意儿对静态图优化狠多了,训练阶段就别折腾compile了。
说实话你这情况我太懂了,我之前用electra小模型试过,提升也就5%-8%,编译那几分钟纯属浪费时间。小数据量小模型真没必要折腾compile,收益还不如把batch size调大点或者用混合精度来得直接。
动态shape报错那个我这边也是,后来直接固定max length做padding,虽然浪费点显存但省心多了。你要是主要图部署推理提速,不如直接上onnxruntime或者tensorrt,比torch.compile稳多了。
顺便问下你自定义分类头那块有没有试过把bert冻结只训头部?我这么干之后训练快了一大截,compile那点提升根本看不上了。
跟你情况差不多,也是2万左右的数据量跑bert,compile那点提升基本被编译时间吃掉了,后来干脆关掉省心。动态shape这块确实坑,transformers里很多op没做静态化适配,报错回退是常态,别太指望。我觉得你这规模真没必要折腾,把精力放数据清洗和调参上收益更大。倒是推理阶段可以试试compile加固定长度,我这边部署时大概能快个20%左右,但训练就别纠结了。不过你要是想深挖,可以试试把padding统一到固定长度再开compile,也许能好点。
说实话你这情况我太熟了,之前用BERT做文本匹配也是被compile折磨过。小数据量+小模型确实没必要硬上,编译开销摊不平,尤其你才2万条,10%的收益可能还没多跑两个epoch划算。我怀疑你那个自定义分类头是不是有什么动态控制流,比如if语句或者根据长度走不同分支,这种会让graph break特别频繁,compile基本就废了。动态shape这个问题无解,除非你固定max_len然后padding到统一长度,但这样又浪费显存,3090虽然够大但也没必要。我后来是这么干的:训练阶段直接关掉compile,纯eager跑,反正小数据量几分钟一个epoch,推理的时候再用torch.compile加dynamic=False,把输入pad到batch内最大长度,这样提速能到20%左右,而且不会报错。你那个部署时想加compile的话,建议先看看有没有静态shape的优化空间,或者试试mode="reduce-overhead",有时候比默认模式稳。另外可以查一下CUDA graphs有没有被自动触发,没触发的话可以手动设torch.cuda.graphs。最后说句实话,transformers库的模型官方优化已经做得很好了,compile能榨的油水真的不多,除非你上大batch或者长序列,不然收益很难看。
同款场景,我试过torch.compile在小模型上确实收益有限,尤其数据量小的时候编译开销占比太高了,10%的提升我觉得算正常水平。动态shape报错太真实了,transformers的tokenizer输出padding长度一变,重新编译比不编译还慢。你如果主要卡在训练,不如先把batch size调大或者用梯度累积,效果可能更直接。至于部署推理,小模型直接上ONNX或者TensorRT吧,比torch.compile稳多了,我上次折腾半天最后也回退了。
我也是2万条数据跑BERT,compile之后的提升基本可以忽略,而且显存还涨了一点。你那个10%我觉得都算好的了,我实测有时候还负优化。动态padding这个问题无解,除非你固定序列长度或者用bucket,但那样预处理又麻烦。个人建议训练阶段别折腾这个了,把精力放在数据增强或者调学习率上,收益更大。推理阶段如果在意延迟,直接转ONNX导出,比compile省心太多。
小模型+小数据量真没必要上compile,我拿GPT2试过,收益还没编译时间多。你报错大概率是graph break导致的,transformers里那些动态控制流跟compile的兼容性本来就一般。想提速不如换个思路,比如用apex的混合精度,3090跑BERT分类随便也能快个2倍,还不用改代码。部署的话
同款配置,不过我是文本匹配任务,batch里塞了不同长度的样本,compile一开动态shape直接崩,后来干脆只在固定长度的场景用。小模型收益确实有限,我试过蒸馏后的tiny bert,提速基本可以忽略,但显存占用倒是降了一点。你那个10%其实不算差,官方benchmark都是大模型大batch堆出来的,2万条数据真没必要折腾这个,部署时直接用ONNX或者TensorRT可能更实在。