Triton 示例后端#
要学习如何创建 Triton 后端,并查看您可以添加自己的后端日志的最佳实践基线,请按照教程进行操作。
Triton 还提供了一些示例后端,演示了教程未涵盖的后端 API 的特定方面。
repeat 后端展示了一个更高级的示例,说明后端如何为每个请求生成多个响应。
stateful 后端展示了一个示例,说明后端如何为序列批处理器管理服务器端的模型状态张量,以避免在客户端和服务器之间传输状态张量。Triton 还实现了隐式状态管理,这允许后端以无状态方式运行,并将状态管理留给 Triton。
教程#
Triton 后端 API 公开了大量功能。后端实用程序和类提供了创建后端时常用的许多功能。但是,要创建功能性后端,不必使用大多数后端 API 或实用程序。本教程从一个展示最小后端的实现开始,然后添加推荐的和可选的增强功能。本教程的实现遵循 Triton 后端的最佳实践,因此可以用作您自己后端的模板。
最小 Triton 后端#
最小后端的源代码包含在minimal.cc中。源代码包含详细的文档,描述了后端的运行以及Triton 后端 API和后端实用程序的使用。在阅读源代码之前,请确保您理解与 Triton 后端抽象TRITONBACKEND_Backend、TRITONBACKEND_Model和TRITONBACKEND_ModelInstance相关的概念。
最小后端不执行任何有趣的操作,它只是将单个输入张量复制到单个输出张量,但它确实演示了 Triton 后端所需的基本组织结构。
最小后端是完整的,但为了清晰起见,省略了编写功能齐全的后端的一些重要方面,这些方面在推荐 Triton 后端中进行了描述。在创建您自己的后端时,请使用推荐 Triton 后端作为起点。
构建最小后端#
backends/minimal/CMakeLists.txt 展示了 Triton 后端的推荐构建和安装脚本。要构建最小后端并安装到本地目录中,请使用以下命令。
$ cd backends/minimal
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX:PATH=`pwd`/install ..
$ make install
以下必需的 Triton 仓库将被拉取并在构建中使用。默认情况下,每个仓库将使用“main”分支/标签,但可以使用列出的 CMake 参数来覆盖。
triton-inference-server/backend: -DTRITON_BACKEND_REPO_TAG=[tag]
triton-inference-server/core: -DTRITON_CORE_REPO_TAG=[tag]
triton-inference-server/common: -DTRITON_COMMON_REPO_TAG=[tag]
如果您在发布分支(或基于发布分支的开发分支)上进行构建,则必须设置这些 cmake 参数以指向该发布分支。例如,如果您正在构建 r21.10 identity_backend 分支,则需要使用以下附加 cmake 标志
-DTRITON_BACKEND_REPO_TAG=r21.10
-DTRITON_CORE_REPO_TAG=r21.10
-DTRITON_COMMON_REPO_TAG=r21.10
构建后,安装目录将包含一个 backends/minimal 目录,其中包含最小后端。有关将此后端添加到 Triton 服务器的说明,请参见后端共享库。
运行带有最小后端的 Triton#
在按照后端共享库中的描述将最小后端添加到 Triton 服务器后,您可以运行 Triton 并使其加载model_repos/minimal_models中的模型。假设您已通过将最小后端添加到 Triton 创建了 tritonserver Docker 镜像,则以下命令将运行 Triton
$ docker run --rm -it --net=host -v/path/to/model_repos/minimal_models:/models tritonserver --model-repository=/models
控制台输出将显示类似于以下内容,表明来自 minimal_models 仓库的 batching 和 nonbatching 模型已正确加载。请注意,模型仓库有两个模型,它们都使用最小后端。一个后端可以支持任意数量的不同模型。
I1215 23:46:00.250284 68 server.cc:589]
+-------------+---------+--------+
| Model | Version | Status |
+-------------+---------+--------+
| batching | 1 | READY |
| nonbatching | 1 | READY |
+-------------+---------+--------+
这些模型是相同的,只是 batching 模型启用了动态批处理器并支持最大批量大小为 8。请注意,batching 模型将批处理延迟设置为 5 秒,以便下面描述的示例客户端可以演示最小后端如何接收一批请求。
测试最小后端#
clients 目录包含示例客户端。minimal_client Python 脚本演示了向最小后端发送几个推理请求。在 Triton 按照运行带有最小后端的 Triton中的描述运行时,执行客户端
$ clients/minimal_client
minimal_client 首先向 nonbatching 模型发送单个请求。从输出中可以看到,输入值在输出中返回。
=========
Sending request to nonbatching model: IN0 = [1 2 3 4]
Response: {'model_name': 'nonbatching', 'model_version': '1', 'outputs': [{'name': 'OUT0', 'datatype': 'INT32', 'shape': [4], 'parameters': {'binary_data_size': 16}}]}
OUT0 = [1 2 3 4]
在 Triton 控制台输出中,您可以看到最小后端打印的日志消息,表明它接收到包含单个请求的批次。
I1221 18:14:12.964836 86 minimal.cc:348] model nonbatching: requests in batch 1
I1221 18:14:12.964857 86 minimal.cc:356] batched IN0 value: [ 1, 2, 3, 4 ]
minimal_client 接下来同时向 batching 模型发送 2 个请求。Triton 将动态地将这些请求批处理到一个批次中,并将该批次发送到最小后端。
=========
Sending request to batching model: IN0 = [[10 11 12 13]]
Sending request to batching model: IN0 = [[20 21 22 23]]
Response: {'model_name': 'batching', 'model_version': '1', 'outputs': [{'name': 'OUT0', 'datatype': 'INT32', 'shape': [1, 4], 'parameters': {'binary_data_size': 16}}]}
OUT0 = [[10 11 12 13]]
Response: {'model_name': 'batching', 'model_version': '1', 'outputs': [{'name': 'OUT0', 'datatype': 'INT32', 'shape': [1, 4], 'parameters': {'binary_data_size': 16}}]}
OUT0 = [[20 21 22 23]]
在 Triton 控制台输出中,您可以看到日志消息,表明最小后端收到了包含两个请求的批次。
I1221 18:14:17.965982 86 minimal.cc:348] model batching: requests in batch 2
I1221 18:14:17.966035 86 minimal.cc:356] batched IN0 value: [ 10, 11, 12, 13, 20, 21, 22, 23 ]
推荐 Triton 后端#
推荐后端的源代码包含在recommended.cc中。源代码包含详细的文档,描述了后端的运行以及Triton 后端 API和后端实用程序的使用。在阅读源代码之前,请确保您理解与 Triton 后端抽象TRITONBACKEND_Backend、TRITONBACKEND_Model和TRITONBACKEND_ModelInstance相关的概念。
推荐后端改进了最小后端,以包含以下功能,这些功能应存在于任何健壮的后端实现中
增强后端以支持具有 INT32 以外数据类型的输入/输出张量的模型。
增强后端以支持具有任何形状的输入/输出张量的模型。
使用 Triton 后端指标 API 记录有关后端中执行的请求的统计信息。然后可以使用 Triton 指标和统计信息 API 查询这些指标。
额外的错误检查,以确保后端的版本与 Triton 兼容,并且每个模型的配置与后端兼容。
与最小后端一样,推荐后端只是在输出张量中返回输入张量值。由于上述添加,推荐后端可以作为您后端的起点。
构建推荐后端#
backends/recommended/CMakeLists.txt 展示了 Triton 后端的推荐构建和安装脚本。构建和安装与构建最小后端中描述的相同。
运行带有推荐后端的 Triton#
在按照后端共享库中的描述将推荐后端添加到 Triton 服务器后,您可以运行 Triton 并使其加载model_repos/recommended_models中的模型。假设您已通过将推荐后端添加到 Triton 创建了 tritonserver Docker 镜像,则以下命令将运行 Triton
$ docker run --rm -it --net=host -v/path/to/model_repos/recommended_models:/models tritonserver --model-repository=/models
控制台输出将显示类似于以下内容,表明来自 recommended_models 仓库的 batching 模型已正确加载。
I1215 23:46:00.250284 68 server.cc:589]
+-------------+---------+--------+
| Model | Version | Status |
+-------------+---------+--------+
| batching | 1 | READY |
+-------------+---------+--------+
测试推荐后端#
clients 目录包含示例客户端。recommended_client Python 脚本演示了向推荐后端发送几个推理请求。在 Triton 按照运行带有推荐后端的 Triton中的描述运行时,执行客户端
$ clients/recommended_client
recommended_client 接下来同时向 batching 模型发送 2 个请求,类似于上面对最小后端的操作。Triton 将动态地将这些请求批处理到一个批次中,并将该批次发送到推荐后端。在此模型中,支持批处理,数据类型为 FP32,张量形状为 [ -1, 4, 4 ]。
=========
Sending request to batching model: input = [[[1. 1.1 1.2 1.3]
[2. 2.1 2.2 2.3]
[3. 3.1 3.2 3.3]
[4. 4.1 4.2 4.3]]]
Sending request to batching model: input = [[[10. 10.1 10.2 10.3]
[20. 20.1 20.2 20.3]
[30. 30.1 30.2 30.3]
[40. 40.1 40.2 40.3]]]
Response: {'model_name': 'batching', 'model_version': '1', 'outputs': [{'name': 'OUTPUT', 'datatype': 'FP32', 'shape': [1, 4, 4], 'parameters': {'binary_data_size': 64}}]}
OUTPUT = [[[1. 1.1 1.2 1.3]
[2. 2.1 2.2 2.3]
[3. 3.1 3.2 3.3]
[4. 4.1 4.2 4.3]]]
Response: {'model_name': 'batching', 'model_version': '1', 'outputs': [{'name': 'OUTPUT', 'datatype': 'FP32', 'shape': [1, 4, 4], 'parameters': {'binary_data_size': 64}}]}
OUTPUT = [[[10. 10.1 10.2 10.3]
[20. 20.1 20.2 20.3]
[30. 30.1 30.2 30.3]
[40. 40.1 40.2 40.3]]]
在 Triton 控制台输出中,您可以看到日志消息,表明推荐后端收到了包含两个请求的批次。
I1221 18:30:52.223226 127 recommended.cc:604] model batching: requests in batch 2
I1221 18:30:52.223313 127 recommended.cc:613] batched INPUT value: [ 1.000000, 1.100000, 1.200000, 1.300000, 2.000000, 2.100000, 2.200000, 2.300000, 3.000000, 3.100000, 3.200000, 3.300000, 4.000000, 4.100000, 4.200000, 4.300000, 10.000000, 10.100000, 10.200000, 10.300000, 20.000000, 20.100000, 20.200001, 20.299999, 30.000000, 30.100000, 30.200001, 30.299999, 40.000000, 40.099998, 40.200001, 40.299999 ]
由于推荐后端可以支持具有任何数据类型和形状的输入/输出张量的模型,因此您可以编辑模型配置和客户端来尝试这些选项。
要查看为这两个推理请求收集的指标,请使用以下命令访问 Triton 的指标端点。
$ curl localhost:8002/metrics
输出将是 Prometheus 数据格式的指标值。指标文档给出了这些指标值的描述。
# HELP nv_inference_request_success Number of successful inference requests, all batch sizes
# TYPE nv_inference_request_success counter
nv_inference_request_success{model="batching",version="1"} 2.000000
# HELP nv_inference_request_failure Number of failed inference requests, all batch sizes
# TYPE nv_inference_request_failure counter
nv_inference_request_failure{model="batching",version="1"} 0.000000
# HELP nv_inference_count Number of inferences performed
# TYPE nv_inference_count counter
nv_inference_count{model="batching",version="1"} 2.000000
# HELP nv_inference_exec_count Number of model executions performed
# TYPE nv_inference_exec_count counter
nv_inference_exec_count{model="batching",version="1"} 1.000000
...
您还可以使用统计信息端点查看收集的统计信息。
$ curl localhost:8000/v2/models/batching/stats
{"model_stats":[{"name":"batching","version":"1","last_inference":1640111452223,"inference_count":2,"execution_count":1,"inference_stats":{"success":{"count":2,"ns":9997025869},"fail":{"count":0,"ns":0},"queue":{"count":2,"ns":9996491319},"compute_input":{"count":2,"ns":95288},"compute_infer":{"count":2,"ns":232202},"compute_output":{"count":2,"ns":195850}},"batch_stats":[{"batch_size":2,"compute_input":{"count":1,"ns":47644},"compute_infer":{"count":1,"ns":116101},"compute_output":{"count":1,"ns":97925}}]}]}
BLS Triton 后端#
请参阅 BLS 后端的文档。
自定义批处理#
使用动态批处理器时,Triton 允许您设置自定义批处理规则。这些规则添加到指定的动态批处理器行为之上。要设置它们,您需要传入一个实现自定义批处理 API 的库。两个示例批处理库位于batching_strategies 目录中。
对于本教程,您可以使用volume_batching示例来设置每个请求的最大字节体积。要构建库并安装到本地目录中,请使用以下命令
$ cd batch_strategies/volume_batching
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX:PATH=`pwd`/install ..
$ make install
接下来,将库移动到所需的位置。您可以通过模型配置传递文件位置。如果未指定,Triton 将按顺序在模型版本、模型和后端目录中查找名为 batchstrategy.so
的库。为了方便起见,我们将通过模型配置传递它。选择一个模型来使用此策略。然后,更新模型配置以包含以下字段
dynamic_batching { }
parameters: { key: "TRITON_BATCH_STRATEGY_PATH", value: {string_value: "/path/to/libtriton_volumebatching.so"}}
parameters { key: "MAX_BATCH_VOLUME_BYTES" value: {string_value: "96"}}
您可以更新路径以指向您的库的文件路径。您还可以更新 MAX_BATCH_VOLUME_BYTES
的值,以设置为您的用例的每个批次的最大体积。启动 Triton 后,您应该看到调度程序为您的模型在默认批处理行为之上应用了体积约束。通过设置最大队列延迟可以使此操作更加明显,以便调度程序有更多时间完成每个批次。例如,您可以将延迟设置为 100,000 微秒。
增强功能#
本节介绍您可以添加的几个可选功能,以增强后端的功能。
自动模型配置生成#
自动模型配置生成通过后端在 TRITONBACKEND_ModelInitialize 期间实现适当的逻辑(例如,在名为 AutoCompleteConfig 的函数中)来启用。对于推荐后端,您将在 ModelState 构造函数中,在调用 ValidateModelConfig 之前,添加对 AutoCompleteConfig 的调用。AutoCompleteConfig 函数可以使用输入张量、输出张量和最大批量大小配置更新模型配置;然后使用 TRITONBACKEND_ModelSetConfig 更新配置。示例可以在ONNXRuntime 后端、TensorFlow 后端和其他后端中找到。
向响应添加键值参数#
后端可以在创建响应之后和发送响应之前的任何时间向响应添加键值对。参数键必须是字符串,参数值可以是字符串、整数或布尔值。以下示例显示了用于设置响应参数的 TRITONBACKEND API。为了提高清晰度,未显示错误检查代码。
TRITONBACKEND_ResponseSetStringParameter(response, "param0", "an example string parameter");
TRITONBACKEND_ResponseSetIntParameter(responses[r], "param1", 42);
TRITONBACKEND_ResponseSetBoolParameter(responses[r], "param2", false);
访问模型仓库中的模型工件#
后端可以访问模型注册表中模型区域中的任何文件。这些文件通常在 TRITONBACKEND_ModelInitialize 期间需要,但也可以在其他时间访问。TRITONBACKEND_ModelRepository API 提供了模型仓库的位置。例如,以下代码可以在 TRITONBACKEND_ModelInitialize 期间运行,以将位置写入日志。
// Can get location of the model artifacts. Normally we would need
// to check the artifact type to make sure it was something we can
// handle... but we are just going to log the location so we don't
// need the check. We would use the location if we wanted to load
// something from the model's repo.
TRITONBACKEND_ArtifactType artifact_type;
const char* clocation;
RETURN_IF_ERROR(
TRITONBACKEND_ModelRepository(model, &artifact_type, &clocation));
LOG_MESSAGE(
TRITONSERVER_LOG_INFO,
(std::string("Repository location: ") + clocation).c_str());
框架后端(例如,TensorRT、ONNXRuntime、TensorFlow、PyTorch)使用此 API 从模型仓库读取实际模型文件。有关如何使用它的示例,请参见这些后端。