性能指南¶
如果你对优化PyTorch模型在TorchServe中服务时的内存使用、延迟或吞吐量感兴趣,那么这篇指南非常适合你。
我们还在此处创建了一个快速检查清单,列出了本页面未涵盖的其他尝试事项。你可以在这里找到检查清单这里。
优化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 图形
您可以在TorchServe中找到所有torch.compile的示例这里
有关 torch.compile GenAI 示例的详细信息,请参阅此 链接
ONNX 和 ORT 支持
TorchServe 对 ONNX 模型有原生支持,可以通过 ORT 加载以加速 CPU 和 GPU 推理。ONNX 的运行方式与普通 PyTorch 模型略有不同,在进行转换时,您需要显式设置并命名输入和输出维度。请参阅 此示例。
从宏观角度来看,TorchServe允许您做的事情是
序列化ONNX权重的包
torch-model-archiver --serialized-file model.onnx ...从
base_handler.py加载那些权重,使用ort_session = ort.InferenceSession(self.model_pt_path, providers=providers, sess_options=sess_options),它支持合理的默认设置,适用于 CPU 和 GPU 推断允许您定义自定义的预处理和后处理函数,以便将数据以您的ONNX模型期望的格式传递给数据,并使用自定义处理器。
要将ONNX与TorchServe Docker上的GPU一起使用,我们需要将NVIDIA CUDA运行时作为基础镜像来构建一个镜像,如这里所示
TensorRT
TorchServe 还支持通过 TensorRT 优化的模型。要利用 TensorRT 运行时,你可以按照以下说明转换你的模型,完成后你将获得序列化的权重,可以使用 torch.jit.load() 加载。
转换后,PyTorch对Torchscript模型和TensorRT模型的处理方式没有区别。
更好的Transformer
PyTorch 中的 Better Transformer 实现了向后兼容的快速路径 torch.nn.TransformerEncoder,用于 Transformer 编码器推理,并且不需要模型作者修改他们的模型。Better Transformer 的改进在许多常见的执行场景中可以超过 2 倍的速度提升和吞吐量。
您可以在这里 这里 和 这里 找到更多关于 Better Transformer 的信息。
优化TorchServe¶
如果您想从config.properties中提高TorchServe的性能,您应该调整的设置是batch_size和batch_delay。较大的批量大小意味着更高的吞吐量,但代价是较低的延迟。
第二重要的设置是工作线程数和GPU数量,这将对CPU和GPU性能产生巨大影响。
并发性和工作线程数
TorchServe提供了配置选项,允许用户配置CPU和GPU上的工作线程数量。有一个重要的配置属性可以根据工作负载的速度来加速服务器。 注意:以下属性在重负载下有更大的影响。
TorchServe 在 CPU 上
如果你在CPU上使用TorchServe,可以通过在你的config.properties中设置以下内容来提高性能:
cpu_launcher_enable=true
cpu_launcher_args=--use_logical_core
这些设置通过启动器核心锁定显著提高了性能。 这一改进背后的理论在这篇博客中进行了讨论,可以简单总结为:
在支持超线程的系统中,避免逻辑核心的方法是通过核心绑定将线程亲和性设置为仅物理核心。
在具有NUMA的多处理器系统中,通过核心绑定将线程亲和性设置为特定的处理器来避免跨处理器远程内存访问。
TorchServe 在 GPU 上
有一个名为number_of_gpu的配置属性,告诉服务器每个模型使用特定数量的GPU。在我们向服务器注册多个模型的情况下,这将适用于所有注册的模型。如果将其设置为低值(例如0或1),会导致GPU资源未充分利用。相反,设置为高值(≥系统中可用的最多GPU数)将导致每个模型分配更多的工作线程。显然,这将导致不必要的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分析器的信息。
更多资源¶
TorchServe 在动画绘画应用中的应用
要深入了解如何在应用程序中优化TorchServe性能,请参阅此文章。这里展示的案例研究使用了Meta的Animated Drawings应用程序来改进TorchServe性能。
性能检查表
我们还在此处创建了一个快速检查清单,列出了本页面未涵盖的其他尝试事项。你可以在这里找到检查清单这里。