优化#
Triton 推理服务器具有许多功能,您可以使用这些功能来减少模型的延迟并提高吞吐量。本节讨论这些功能,并演示如何使用它们来提高模型的性能。作为先决条件,您应该遵循 快速入门,以使 Triton 和客户端示例与示例模型仓库一起运行。
本节重点介绍了解单个模型的延迟和吞吐量权衡。模型分析器 章节介绍了一个工具,可帮助您了解模型的 GPU 内存利用率,以便您可以决定如何在单个 GPU 上最佳运行多个模型。
除非您已经有一个适合测量模型在 Triton 上的性能的客户端应用程序,否则您应该熟悉 性能分析器。性能分析器是优化模型性能的必备工具。
作为演示优化特性和选项的运行示例,我们将使用 TensorFlow Inception 模型,您可以通过遵循 快速入门 来获取该模型。作为基线,我们使用 perf_analyzer 来确定使用 不启用任何性能特性的基本模型配置 的模型性能。
$ perf_analyzer -m inception_graphdef --percentile=95 --concurrency-range 1:4
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 1, throughput: 62.6 infer/sec, latency 21371 usec
Concurrency: 2, throughput: 73.2 infer/sec, latency 34381 usec
Concurrency: 3, throughput: 73.2 infer/sec, latency 50298 usec
Concurrency: 4, throughput: 73.4 infer/sec, latency 65569 usec
结果表明,我们未优化的模型配置提供的吞吐量约为每秒 73 次推理。请注意,从一个并发请求到两个并发请求,吞吐量显着增加,然后吞吐量趋于平稳。在一个并发请求的情况下,当响应返回给客户端并且服务器接收到下一个请求时,Triton 处于空闲状态。吞吐量在并发度为 2 时增加,因为 Triton 将一个请求的处理与另一个请求的通信重叠。由于我们在与 Triton 相同的系统上运行 perf_analyzer,因此两个请求足以完全隐藏通信延迟。
优化设置#
对于大多数模型来说,Triton 提供最大性能改进的功能是 动态批处理。此示例 更详细地阐述了概念细节。如果您的模型不支持批处理,则可以跳到 模型实例。
动态批处理器#
动态批处理器将单个推理请求组合成更大的批次,与独立执行单个请求相比,这通常会更有效地执行。要启用动态批处理器,请停止 Triton,将以下行添加到 inception_graphdef 的模型配置文件 的末尾,然后重新启动 Triton。
dynamic_batching { }
动态批处理器允许 Triton 处理更高数量的并发请求,因为这些请求被组合在一起进行推理。要查看这一点,请使用请求并发度从 1 到 8 运行 perf_analyzer。
$ perf_analyzer -m inception_graphdef --percentile=95 --concurrency-range 1:8
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 1, throughput: 66.8 infer/sec, latency 19785 usec
Concurrency: 2, throughput: 80.8 infer/sec, latency 30732 usec
Concurrency: 3, throughput: 118 infer/sec, latency 32968 usec
Concurrency: 4, throughput: 165.2 infer/sec, latency 32974 usec
Concurrency: 5, throughput: 194.4 infer/sec, latency 33035 usec
Concurrency: 6, throughput: 217.6 infer/sec, latency 34258 usec
Concurrency: 7, throughput: 249.8 infer/sec, latency 34522 usec
Concurrency: 8, throughput: 272 infer/sec, latency 35988 usec
在八个并发请求的情况下,动态批处理器允许 Triton 提供每秒 272 次推理,而与不使用动态批处理器相比,延迟没有增加。
与其让 perf_analyzer 收集一系列请求并发度值的数据,不如使用一些简单的规则,这些规则通常适用于 perf_analyzer 在与 Triton 相同的系统上运行时。第一个规则是,对于最小延迟,将请求并发度设置为 1,禁用动态批处理器,并且仅使用 1 个 模型实例。第二个规则是,对于最大吞吐量,将请求并发度设置为 2 * <最大 批次 大小> * <模型 实例 计数>
。我们将在 下面 讨论模型实例,现在我们正在使用一个模型实例。因此,对于最大批次大小为 4,我们希望以 2 * 4 * 1 = 8
的请求并发度运行 perf_analyzer。
$ perf_analyzer -m inception_graphdef --percentile=95 --concurrency-range 8
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 8, throughput: 267.8 infer/sec, latency 35590 usec
模型实例#
Triton 允许您指定要为推理提供多少个模型的副本。默认情况下,您获得每个模型的一个副本,但是您可以使用 实例组 在模型配置中指定任意数量的实例。通常,拥有模型的两个实例将提高性能,因为它允许内存传输操作(例如,CPU 到/从 GPU)与推理计算重叠。多个实例还可以通过允许在 GPU 上同时执行更多推理工作来提高 GPU 利用率。较小的模型可能会受益于两个以上的实例;您可以使用 perf_analyzer 进行实验。
要指定 inception_graphdef 模型的两个实例:停止 Triton,删除您之前添加到模型配置中的任何动态批处理设置(我们将在下面讨论组合动态批处理器和多个模型实例),将以下行添加到 模型配置文件 的末尾,然后重新启动 Triton。
instance_group [ { count: 2 }]
现在使用与基线相同的选项运行 perf_analyzer。
$ perf_analyzer -m inception_graphdef --percentile=95 --concurrency-range 1:4
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 1, throughput: 70.6 infer/sec, latency 19547 usec
Concurrency: 2, throughput: 106.6 infer/sec, latency 23532 usec
Concurrency: 3, throughput: 110.2 infer/sec, latency 36649 usec
Concurrency: 4, throughput: 108.6 infer/sec, latency 43588 usec
在这种情况下,与一个实例相比,拥有模型的两个实例将吞吐量从大约每秒 73 次推理提高到大约每秒 110 次推理。
可以同时启用动态批处理器和多个模型实例,例如,更改模型配置文件以包含以下内容。
dynamic_batching { }
instance_group [ { count: 2 }]
当我们使用与上面仅使用动态批处理器相同的选项运行 perf_analyzer 时。
$ perf_analyzer -m inception_graphdef --percentile=95 --concurrency-range 16
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 16, throughput: 289.6 infer/sec, latency 59817 usec
我们看到,与仅使用动态批处理器和一个实例相比,两个实例并没有显着提高吞吐量,反而增加了延迟。发生这种情况是因为对于此模型,仅动态批处理器就能够充分利用 GPU,因此添加额外的模型实例不会提供任何性能优势。一般来说,动态批处理器和多个实例的优势是特定于模型的,因此您应该使用 perf_analyzer 进行实验,以确定最满足您的吞吐量和延迟要求的设置。
框架特定的优化#
Triton 具有多个优化设置,这些设置仅适用于部分受支持的模型框架。这些优化设置由模型配置 优化策略 控制。访问 本指南 以进行端到端讨论。
使用 TensorRT 优化 ONNX (ORT-TRT)#
一个特别强大的优化是将 TensorRT 与 ONNX 模型结合使用。作为应用于 ONNX 模型的 TensorRT 优化的示例,我们将使用 ONNX DenseNet 模型,您可以通过遵循 快速入门 来获取该模型。作为基线,我们使用 perf_analyzer 来确定使用 不启用任何性能特性的基本模型配置 的模型性能。
$ perf_analyzer -m densenet_onnx --percentile=95 --concurrency-range 1:4
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 1, 113.2 infer/sec, latency 8939 usec
Concurrency: 2, 138.2 infer/sec, latency 14548 usec
Concurrency: 3, 137.2 infer/sec, latency 21947 usec
Concurrency: 4, 136.8 infer/sec, latency 29661 usec
要为模型启用 TensorRT 优化:停止 Triton,将以下行添加到模型配置文件的末尾,然后重新启动 Triton。
optimization { execution_accelerators {
gpu_execution_accelerator : [ {
name : "tensorrt"
parameters { key: "precision_mode" value: "FP16" }
parameters { key: "max_workspace_size_bytes" value: "1073741824" }
}]
}}
当 Triton 启动时,您应该检查控制台输出并等待直到 Triton 打印 “Staring endpoints” 消息。启用 TensorRT 优化后,ONNX 模型加载可能会显着变慢。在生产环境中,您可以使用 模型预热 来避免这种模型启动/优化减速。现在使用与基线相同的选项运行 perf_analyzer。
$ perf_analyzer -m densenet_onnx --percentile=95 --concurrency-range 1:4
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 1, 190.6 infer/sec, latency 5384 usec
Concurrency: 2, 273.8 infer/sec, latency 7347 usec
Concurrency: 3, 272.2 infer/sec, latency 11046 usec
Concurrency: 4, 266.8 infer/sec, latency 15089 usec
TensorRT 优化提供了 2 倍的吞吐量提升,同时将延迟减少了一半。TensorRT 提供的优势将因模型而异,但总的来说,它可以提供显着的性能改进。
使用 OpenVINO 优化 ONNX#
在 CPU 上运行的 ONNX 模型也可以通过使用 OpenVINO 来加速。要为 ONNX 模型启用 OpenVINO 优化,请将以下行添加到模型的配置文件末尾。
optimization { execution_accelerators {
cpu_execution_accelerator : [ {
name : "openvino"
}]
}}
使用 TensorRT 优化 TensorFlow (TF-TRT)#
应用于 TensorFlow 模型的 TensorRT 优化与上面描述的 TensorRT 和 ONNX 类似。要启用 TensorRT 优化,您必须适当地设置模型配置。对于 TensorFlow 模型的 TensorRT 优化,您可以启用多个选项,包括选择计算精度。
optimization { execution_accelerators {
gpu_execution_accelerator : [ {
name : "tensorrt"
parameters { key: "precision_mode" value: "FP16" }}]
}}
这些选项在模型配置 protobuf 的 ModelOptimizationPolicy 部分中详细描述。
作为应用于 TensorFlow 模型的 TensorRT 优化的示例,我们将使用 TensorFlow Inception 模型,您可以通过遵循 快速入门 来获取该模型。作为基线,我们使用 perf_analyzer 来确定使用 不启用任何性能特性的基本模型配置 的模型性能。
$ perf_analyzer -m inception_graphdef --percentile=95 --concurrency-range 1:4
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 1, throughput: 62.6 infer/sec, latency 21371 usec
Concurrency: 2, throughput: 73.2 infer/sec, latency 34381 usec
Concurrency: 3, throughput: 73.2 infer/sec, latency 50298 usec
Concurrency: 4, throughput: 73.4 infer/sec, latency 65569 usec
要为模型启用 TensorRT 优化:停止 Triton,将上面的行添加到模型配置文件的末尾,然后重新启动 Triton。当 Triton 启动时,您应该检查控制台输出并等待直到服务器打印 “Staring endpoints” 消息。现在使用与基线相同的选项运行 perf_analyzer。请注意,perf_analyzer 的首次运行可能会超时,因为 TensorRT 优化是在接收到推理请求时执行的,并且可能需要相当长的时间。在生产环境中,您可以使用 模型预热 来避免这种模型启动/优化减速。现在,如果发生这种情况,只需再次运行 perf_analyzer。
$ perf_analyzer -m inception_graphdef --percentile=95 --concurrency-range 1:4
...
Inferences/Second vs. Client p95 Batch Latency
Concurrency: 1, throughput: 140 infer/sec, latency 8987 usec
Concurrency: 2, throughput: 195.6 infer/sec, latency 12583 usec
Concurrency: 3, throughput: 189 infer/sec, latency 19020 usec
Concurrency: 4, throughput: 191.6 infer/sec, latency 24622 usec
TensorRT 优化提供了 2.5 倍的吞吐量提升,同时将延迟减少了一半以上。TensorRT 提供的优势将因模型而异,但总的来说,它可以提供显着的性能改进。
TensorFlow JIT 图优化#
Tensorflow 允许其用户通过 GlobalJitLevel 设置指定运行模型图时的优化级别。有关更多信息,请参阅 config.proto。在 Triton 中运行 TensorFlow 模型时,用户可以通过提供如下所示的图级别来提供此设置
optimization {
graph { level: 1
}}
用户还可以通过在启动 Triton 之前设置 TF_XLA_FLAGS
环境变量来利用 XLA 优化。以下是启动带有 GPU 和 CPU 自动集群的 Triton 的示例
$ TF_XLA_FLAGS="--tf_xla_auto_jit=2 --tf_xla_cpu_global_jit" tritonserver --model-repository=...
与上面的 TensorRT 优化的情况一样,这些优化发生在运行第一个推理请求时。为了减轻生产系统中的模型启动减速,您可以使用 模型预热。
TensorFlow 自动 FP16 优化#
TensorFlow 有一个提供 FP16 优化的选项,可以在模型配置中启用。与上面描述的 TensorRT 优化一样,您可以使用 gpu_execution_accelerator 属性启用此优化。
optimization { execution_accelerators {
gpu_execution_accelerator : [
{ name : "auto_mixed_precision" }
]
}}
这些选项在模型配置 protobuf 的 ModelOptimizationPolicy 部分中详细描述。
您可以按照上面针对 TensorRT 描述的步骤来了解这种自动 FP16 优化如何使模型受益,方法是使用 perf_analyzer 来评估模型在启用和不启用优化时的性能。
NUMA 优化#
许多现代 CPU 由多个内核、内存和互连组成,这些内核、内存和互连根据线程和数据的分配方式呈现不同的性能特征。Triton 允许您设置主机策略,这些策略描述系统的 NUMA 配置,然后将模型实例分配给不同的主机策略以利用这些 NUMA 属性。
主机策略#
Triton 允许您指定在启动时与策略名称关联的主机策略。如果实例在使用 实例组 中的主机策略字段指定了相同的策略名称,则主机策略将应用于模型实例。请注意,如果未指定,主机策略字段将根据实例属性设置为默认名称。
要指定主机策略,您可以在命令行选项中指定以下内容
--host-policy=<policy_name>,<setting>=<value>
目前,支持的设置如下:
numa-node:主机策略将绑定到的 NUMA 节点 ID,主机策略将内存分配限制为指定的节点。
cpu-cores:要运行的 CPU 核心,设置此主机策略的实例将在这些 CPU 核心之一上运行。
假设系统配置为将 GPU 0 与 NUMA 节点 0 绑定,NUMA 节点 0 具有从 0 到 15 的 CPU 核心,则以下显示了为 “gpu_0” 设置 numa-node 和 cpu-cores 策略
$ tritonserver --host-policy=gpu_0,numa-node=0 --host-policy=gpu_0,cpu-cores=0-15 ...