Triton教程 — 优化
Triton系列教程:
- 快速开始
- 利用Triton部署你自己的模型
- Triton架构
- 模型仓库
- 存储代理
- 模型设置
- 优化
- 动态批处理
文章目录
- Triton教程 --- 优化
- 优化设置
- 动态批处理程序
- 模型实例
- 特定于框架的优化
- 带有 TensorRT 优化的 ONNX (ORT-TRT)
- 具有 OpenVINO 优化的 ONNX
- TensorFlow 与 TensorRT 优化 (TF-TRT)
- TensorFlow JIT 图优化
- TensorFlow 自动 FP16 优化
- NUMA优化
- 主机策略
Triton 推理服务器具有许多功能,您可以使用这些功能来减少延迟并增加模型的吞吐量。 本节讨论这些功能并演示如何使用它们来提高模型的性能。 作为先决条件,您应该按照 QuickStart 获取 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 在响应返回给客户端和服务器接收到下一个请求期间处于空闲状态。 吞吐量随着并发数的增加而增加,因为 Triton 将一个请求的处理与另一个请求的通信重叠。 因为我们在与 Triton 相同的系统上运行 perf_analyzer,所以两个请求足以完全隐藏通信延迟。
优化设置
对于大多数模型,提供最大性能改进的 Triton 功能是动态批处理。 这个例子更清楚地说明了概念细节。 如果您的模型不支持批处理,那么您可以跳到模型实例。
动态批处理程序
动态批处理程序将单个推理请求组合成一个更大的批处理,这通常比单独执行单个请求的执行效率更高。 要启用动态批处理程序停止 Triton,请将以下行添加到 inception_graphdef 模型配置文件的末尾,然后重新启动 Triton。
dynamic_batching { }
动态批处理程序允许 Triton 处理更多的并发请求,因为这些请求被组合起来进行推理。 要查看此运行 perf_analyzer,并发请求从 1 到 8。
$ 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 并禁用动态批处理程序并仅使用一个模型实例。 第二条规则是,对于最大吞吐量,将请求并发设置为 2 * <maximum batch size> * <model instance count>
。 我们将在下面讨论模型实例,目前我们正在处理一个模型实例。 因此,对于 maximum-batch-size 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"}]
}}
TensorFlow 与 TensorRT 优化 (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 描述的步骤,通过使用 perf_analyzer 来评估模型在优化和不优化的情况下的性能,从而了解这种自动 FP16 优化如何使模型受益。
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 的 CPU 核心数为 0 到 15,下面显示了为“gpu_0”设置 numa-node 和 cpu-cores 策略:
$ tritonserver --host-policy=gpu_0,numa-node=0 --host-policy=gpu_0,cpu-cores=0-15 ...