模型推理优化清单¶
此清单描述了诊断模型推理性能问题时应完成的一些步骤。其中一些建议仅适用于 NLP 模型(例如,确保输入没有过度填充和序列分桶),但一般原则也适用于其他模型。
一般系统优化¶
检查 PyTorch、Nvidia 驱动程序和其他组件的版本,并更新到最新的兼容版本。通常已修复已知的性能错误。
收集系统级活动日志以了解整体资源利用率。了解模型推理管道如何在高级别使用系统资源作为优化的第一步非常有用。即使是简单的 CLI 工具(如 nvidia-smi 和 htop)也可能有所帮助。
从对性能影响最大的目标开始。从系统活动日志中应该很明显瓶颈在哪里 - 不要局限于模型推理,因为预处理/后处理可能很昂贵,并且会像影响端到端吞吐量一样影响端到端吞吐量。
量化并降低磁盘和网络等缓慢 I/O 对端到端性能的影响。虽然优化 I/O 超出了本清单的范围,但请查找使用异步、并发、流水线等技术有效“隐藏” I/O 成本的技术。
对于对长度可变的输入序列进行模型推理(例如,用于 NLP 的转换器),请确保标记器没有过度填充输入。如果转换器经过训练,填充到恒定长度(例如,512),并在部署时使用相同的填充,则它在短序列上的运行速度会不必要地慢(数量级)。
使用 JPEG 格式输入的视觉模型通常受益于 CPU 上更快的 JPEG 解码(例如 libjpeg-turbo 和 Pillow-SIMD),以及 GPU 上的解码(例如 torchvision.io.decode_jpeg 和 Nvidia DALI)。如本 示例 所示,即使在旧的 K80 GPU 上,Nvidia DALI 也比 torchvision 快约 20%。
模型推理优化¶
仅在广泛评估和解决其他因素(“低悬的果实”)后,才开始模型推理优化。
在调用模型上的前向传递之前使用
with torch.inference_mode()
上下文或在inference()
方法上使用@torch.inference_mode()
装饰器可以提高推理性能。这是通过 禁用 视图跟踪和版本计数器递增来实现的。对 GPU 推理使用 fp16。在具有张量核心的较新 GPU 上,速度很可能会提高一倍以上,并且精度下降可以忽略不计。从技术上讲,fp16 是一种量化类型,但由于它很少在推理中造成精度损失,因此应始终进行探索。如本文 所述,在大型神经网络应用程序中使用 fp16 可以提高速度。
对 CPU 推理使用模型量化(即 int8)。探索不同的量化选项:动态量化、静态量化和量化感知训练,以及提供更复杂量化方法的工具(例如 Intel Neural Compressor)。值得注意的是,量化会带来一些精度损失,并且可能并不总是能在某些硬件上提供显着的加速,因此这可能并不总是正确的方法。
通过智能批处理平衡吞吐量和延迟。在满足延迟 SLA 的同时,尝试使用更大的批处理大小来提高吞吐量。
尝试使用优化的推理引擎,例如 onnxruntime、tensorRT、lightseq、ctranslate-2 等。这些引擎通常除了模型量化之外,还提供其他优化,例如算子融合。
尝试模型蒸馏。这更复杂,通常需要训练数据,但潜在的收益可能很大。例如,MiniLM 实现了原始 BERT 基础模型 99% 的准确率,同时速度提高了 2 倍。
如果在 CPU 上工作,可以尝试核心固定。您可以在 此博文中 找到有关如何使用此功能的更多信息。
对于对不同长度的序列进行批量处理,序列分桶可能会将吞吐量提高 2 倍。在这种情况下,序列分桶的简单实现是在将输入馈送到模型之前按序列长度对所有输入进行排序,因为这减少了批处理序列时不必要的填充。
虽然此清单并不详尽,但浏览这些项目可能会帮助您从模型推理管道中获得更多性能。