性能指南¶
如果您有兴趣优化使用 TorchServe 提供的 PyTorch 模型的内存使用、延迟或吞吐量,本指南将为您提供帮助。
我们还在此处创建了一个快速清单,列出本页未涵盖的其他尝试事项。您可以在此处找到该清单。
优化 PyTorch¶
有许多优化 PyTorch 模型以用于生产的技巧,包括但不限于蒸馏、量化、融合、剪枝、设置环境变量,我们鼓励您进行基准测试,看看哪种方法最适合您。
总的来说,优化模型很困难,最简单的方法是导出到某些运行时,例如 ORT、TensorRT、IPEX 或 FasterTransformer。我们在 TorchServe github 页面上有很多关于如何集成这些运行时的示例。如果您喜欢的运行时不受支持,请随时打开 PR。
torch.compile
从 PyTorch 2.0 开始,torch.compile
为大量模型提供了开箱即用的加速(约 1.8 倍)。您可以参考此仪表板,该仪表板每晚跟踪此情况。
经过 torch.compile
完全优化的模型显示性能提升高达 10 倍
当使用较小的批量大小时,将 mode="reduce-overhead"
与 torch.compile
一起使用可以提高性能,因为它使用了 CUDA 图
您可以在此处找到 torch.compile
与 TorchServe 的所有示例
有关 torch.compile
GenAI 示例的详细信息,请访问此链接
ONNX 和 ORT 支持
TorchServe 原生支持 ONNX 模型,可以通过 ORT 加载 ONNX 模型以进行加速的 CPU 和 GPU 推理。 ONNX 的运行方式与常规 PyTorch 模型略有不同,因为在运行转换时,您需要显式设置和命名输入和输出维度。请参阅此示例。
从高层次来看,TorchServe 允许您执行以下操作:
打包序列化的 ONNX 权重
torch-model-archiver --serialized-file model.onnx ...
使用
ort_session = ort.InferenceSession(self.model_pt_path, providers=providers, sess_options=sess_options)
从base_handler.py
加载这些权重,该方法支持 CPU 和 GPU 推理的合理默认值允许您定义自定义的预处理和后处理函数,以便使用自定义处理程序以 onnx 模型期望的格式传入数据
要在 TorchServe Docker 上将 ONNX 与 GPU 一起使用,我们需要构建一个以 NVIDIA CUDA 运行时为基础镜像的镜像,如此处所示
TensorRT
TorchServe 还支持通过 TensorRT 优化的模型。要利用 TensorRT 运行时,您可以按照这些说明转换您的模型,完成后,您将获得可以使用 torch.jit.load()
加载的序列化权重。
转换后,PyTorch 处理 Torchscript 模型与 TensorRT 模型的方式没有区别。
Better Transformer
PyTorch 的 Better Transformer 为 Transformer 编码器推理实现了向后兼容的 torch.nn.TransformerEncoder
快速路径,并且不需要模型作者修改他们的模型。对于许多常见的执行场景,BetterTransformer 的改进可以将速度和吞吐量提高 2 倍以上。您可以在此处和此处找到有关 Better Transformer 的更多信息。
优化 TorchServe¶
如果您尝试从 config.properties
提高 TorchServe 的性能,您应该更改的主要设置是 batch_size
和 batch_delay
。更大的批量大小意味着更高的吞吐量,但代价是更低的延迟。
第二重要的设置是 worker 数量和 gpu 数量,这将对 CPU 和 GPU 性能产生巨大影响。
并发和 worker 数量
TorchServe 公开了允许用户配置 CPU 和 GPU 上 worker 线程数量的配置。有一个重要的配置属性可以根据工作负载加速服务器。注意:以下属性在重负载下影响更大。
CPU 上的 TorchServe
如果在 CPU 上使用 TorchServe,您可以通过在 config.properties
中设置以下内容来提高性能
cpu_launcher_enable=true
cpu_launcher_args=--use_logical_core
这些设置通过启动器核心绑定显着提高性能。此改进背后的理论在本文中讨论,可以快速总结为
在启用超线程的系统中,通过核心绑定将线程亲和性仅设置为物理核心,从而避免逻辑核心。
在具有 NUMA 的多插槽系统中,通过核心绑定将线程亲和性设置为特定插槽,从而避免跨插槽远程内存访问。
GPU 上的 TorchServe
有一个名为 number_of_gpu
的配置属性,它告诉服务器为每个模型使用特定数量的 GPU。在向服务器注册多个模型的情况下,这将应用于所有注册的模型。如果将其设置为较低的值(例如:0 或 1),将导致 GPU 利用不足。相反,将其设置为较高的值(>= 系统上可用的最大 GPU 数量)将导致每个模型生成尽可能多的 worker。显然,这将导致 GPU 的不必要争用,并可能导致线程到 GPU 的次优调度。
ValueToSet = (Number of Hardware GPUs) / (Number of Unique Models)
NVIDIA MPS
虽然 NVIDIA GPU 允许在 CUDA 内核上运行多个进程,但这也有其自身的缺点,即
内核的执行通常是串行的
每个进程都创建自己的 CUDA 上下文,这会占用额外的 GPU 内存
为了解决这些缺点,您可以利用 NVIDIA 多进程服务 (MPS) 来提高性能。您可以在此处找到有关如何将 NVIDIA MPS 与 TorchServe 一起使用的更多信息。
NVIDIA DALI
NVIDIA 数据加载库 (DALI) 是一个用于数据加载和预处理的库,旨在加速深度学习应用程序。它可以作为流行的深度学习框架中内置数据加载器和数据迭代器的便携式即插即用替代品。 DALI 提供了一系列高度优化的构建块,用于加载和处理图像、视频和音频数据。您可以在此处找到 DALI 优化与 TorchServe 集成的示例。
基准测试¶
为了更轻松地比较各种模型和 TorchServe 配置,我们添加了一些辅助脚本,这些脚本在此处以清晰的报告输出 p50、p90、p99 延迟等性能数据,并且主要要求您通过 JSON 或 YAML 确定一些配置。您可以在此处找到有关 TorchServe 基准测试的更多信息。
性能分析¶
TorchServe 原生支持 PyTorch 性能分析器,这将帮助您找到代码中的性能瓶颈。
如果您创建了自定义 handle
或 initialize
方法来覆盖 BaseHandler,则必须定义 self.manifest
属性才能运行 _infer_with_profiler
。
export ENABLE_TORCH_PROFILER=TRUE
访问此链接以了解有关 PyTorch 性能分析器的更多信息。
更多资源¶
Animated Drawings App 上的 TorchServe
为了深入了解如何在应用程序中微调 TorchServe 性能,请查看本文。此处显示的案例研究使用了 Meta 的 Animated Drawings App 来提高 TorchServe 性能。
性能检查清单
我们还在此处创建了一个快速清单,列出本页未涵盖的其他尝试事项。您可以在此处找到该清单。