timm 的 fast-norm 开关怎么在 benchmark.py 中启用并验证 GroupNorm/LayerNorm 推理提速?
【免费下载链接】pytorch-image-modelsThe largest collection of PyTorch image encoders / backbones. Including train, eval, inference, export scripts, and pretrained weights -- ResNet, ResNeXT, EfficientNet, NFNet, Vision Transformer (ViT), MobileNetV4, MobileNet-V3 & V2, RegNet, DPN, CSPNet, Swin Transformer, MaxViT, CoAtNet, ConvNeXt, and more项目地址: https://gitcode.com/GitHub_Trending/py/pytorch-image-models
如果你在 timm 中跑 Vision Transformer 这类以 LayerNorm 为主、或含 GroupNorm 的模型,并想量化"快速归一化"对推理速度的实际影响,仓库自带的 benchmark.py 就提供了现成的入口:一个--fast-norm命令行开关,配合--bench inference做同条件对比,最后从samples/sec和ms/step读数判断收益。适用前提是已安装 timm(依赖见 requirements.txt:torch>=1.7、torchvision、pyyaml、huggingface_hub、safetensors、numpy)并在 CUDA 环境下运行(脚本--device默认cuda,且 AMP 路径只在 autocast 启用时生效)。
--fast-norm开关的生效链路
理解开关如何进入模型,才能解释为什么两次运行结果会有差异。整条链路是:
- benchmark.py 定义参数:
parser.add_argument('--fast-norm', default=False, action='store_true', help='enable experimental fast-norm'),注意官方 help 文本把它标注为experimental。 main()中在创建任何模型之前执行if args.fast_norm: set_fast_norm(),set_fast_norm来自timm.layers。- timm/layers/fast_norm.py 中模块级标志
_USE_FAST_NORM默认是False,set_fast_norm(enable=True)将其置位;is_fast_norm()读取该标志。 - 模型里的归一化层在
__init__时把标志缓存为self._fast_norm = is_fast_norm()(见 timm/layers/norm.py 的GroupNorm/LayerNorm及 timm/layers/norm_act.py 的GroupNormAct/LayerNormAct等),forward中据此二选一:
def forward(self, x): if self._fast_norm: x = fast_layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) else: x = F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps) ...fast 版函数与标准版的差别在 timm/layers/fast_norm.py 的模块 docstring 里写得很明确:
For GroupNorm and LayerNorm these functions bypass typical AMP upcast to float32. Additionally, for LayerNorm, the APEX fused LN is used if available (which also does not upcast)
具体行为:fast_group_norm在 autocast 启用时把输入和 weight/bias 转为 autocast 的低精度 dtype,并在关闭 autocast 的上下文中执行F.group_norm,从而跳过 AMP 对 GroupNorm 输入上转到 float32 的默认行为;fast_layer_norm则优先调用 apex 的fused_layer_norm_affine(如果安装了 apex),否则走同样的跳过上转逻辑。
由此推出两条判断依据,后面读数时会用到:
fast_group_norm的行为分支只在is_autocast_enabled为真时改变,也就是说 GroupNorm 要看到 fast-norm 的效果,必须开 AMP(--amp);- LayerNorm 的 fast 路径在安装了 apex 时无需 AMP 也会走 fused LN;两者都没有时,float32 下 fast 版与标准版执行路径基本一致。
另有一个顺序约束:标志是在归一化层__init__时捕获的,benchmark.py中set_fast_norm()位于create_model之前,满足这一顺序;如果你在自己的脚本里复刻这个流程,也必须先调set_fast_norm()再建模型,否则模型仍使用标准归一化。
执行步骤
选一个使用 LayerNorm 的模型做测试对象比较合理——ViT 系模型是 benchmark 覆盖过的标准对象,例如results/下各 benchmark-infer-amp-*.csv 中都有vit_base_patch16_224的记录。用同一个模型跑两组命令,除--fast-norm外其余参数完全一致,才能归因于开关本身。
先跑基线(不带开关):
python benchmark.py -m vit_base_patch16_224 --bench inference --amp -b 256再跑启用 fast-norm 的对照组:
python benchmark.py -m vit_base_patch16_224 --bench inference --amp -b 256 --fast-norm各参数含义(均来自 benchmark.py 的参数定义):
--bench inference:只跑推理基准,跳过训练步骤;默认值是both,此处限定任务;--amp:启用 PyTorch 原生 AMP 混合精度,这是 GroupNorm fast 路径生效的必要条件;-b 256:batch size,-b的默认值就是 256;显存不足时脚本会自动递减 batch size 重试(--no-retry可关闭该重试);- 预热与测量轮数用默认即可:
--num-warm-iter 10、--num-bench-iter 40。
如果只想留档对比,给命令追加--results-file输出 CSV,例如--results-file baseline.csv与--results-file fast_norm.csv。单模型模式下该文件的字段由脚本的结果字典决定:model、infer_samples_per_sec、infer_step_time、infer_batch_size、infer_img_size、param_count,安装了 deepspeed 或 fvcore 时还会多出infer_gmacs/infer_macts。
如何读结果、判断有没有提速
每次运行结束时,日志会输出这样一行收尾信息(数值随你的硬件和配置变化,不是固定预期):
Inference benchmark of vit_base_patch16_224 done. 0000.00 samples/sec, 00.00 ms/step同时 stdout 末尾会打印一段 JSON(--result分隔符后,代码注释说明它是供 runner 脚本解析的),其中的infer_samples_per_sec与infer_step_time就是对比依据:
- 分别记录两次运行的
infer_samples_per_sec(越大越快)和infer_step_time(ms/step,越小越快); - 两次运行在相同
infer_batch_size、相同infer_img_size下才可比;若某次触发了 batch size 递减重试,日志中会出现Reducing batch size to ... for retry.,此时先对齐 batch size 再比; - 仓库
results/目录下的 CSV(如 benchmark-infer-amp-nchw-pt210-cu121-rtx3090.csv)是官方在不同显卡/PyTorch 版本上留下的基准记录,只能用于参考同环境量级,不能当作你本机的预期值。
关于"提速"本身需要保持克制:fast-norm 改变的是归一化在 AMP 下是否跳过 float32 上转,收益大小取决于该模型中 GroupNorm/LayerNorm 在总耗时里的占比。文档没有给出固定收益数字,所以正确的做法就是以上述 A/B 读数为准,读数无差异不代表配置错误,可能只是该模型上归一化开销占比小。
边界与已知限制
- 开关在 help 文本中被标注为 experimental;timm/layers/fast_norm.py 中也有注释
fast (ie lower precision LN) can be disabled with this flag if issues crop up,即这是官方预留的精度行为变更点,出问题时可去掉开关回到标准路径。 --fast-norm是进程级全局标志,只影响之后创建的模型。benchmark.py的单模型流程没有顺序问题;但用--model-list跑批量模型时,所有模型都在标志置位后创建,全部走 fast 路径。- 与
--torchscript组合时不会生效:fast_group_norm/fast_layer_norm内部有torch.jit.is_scripting()分支,直接回退到标准F.group_norm/F.layer_norm。 - 精度相关实验不要混入对比:
--precision、--channels-last、--reparam等会独立改变计时结果,A/B 两次运行中保持它们一致。 - 不要把 fast-norm 理解为量化或改变整体计算精度,它只改变 GroupNorm/LayerNorm(fast_norm.py 中还有对应 RMSNorm 的 fast 变体)在 AMP 下的上转行为。
如果确认 fast-norm 对你的模型有效,下一步可以在 ImageNet 验证集上核对精度影响:validate.py 提供了同名--fast-norm开关,用法与 benchmark 一致。
【免费下载链接】pytorch-image-modelsThe largest collection of PyTorch image encoders / backbones. Including train, eval, inference, export scripts, and pretrained weights -- ResNet, ResNeXT, EfficientNet, NFNet, Vision Transformer (ViT), MobileNetV4, MobileNet-V3 & V2, RegNet, DPN, CSPNet, Swin Transformer, MaxViT, CoAtNet, ConvNeXt, and more项目地址: https://gitcode.com/GitHub_Trending/py/pytorch-image-models
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考