License

Triton 推理服务器后端#

Triton 后端是执行模型的实现。后端可以是深度学习框架(如 PyTorch、TensorFlow、TensorRT 或 ONNX Runtime)的包装器。或者,后端可以是执行任何操作(例如,图像预处理)的自定义 C/C++ 逻辑。

此仓库包含有关 Triton 后端的文档,以及用于创建 Triton 后端的源代码、脚本和实用程序。您无需使用此仓库中提供的任何内容来创建 Triton 后端,但您可能会发现其内容很有用。

常见问题解答#

完整的文档包含在下面,但这些快捷方式可以帮助您朝着正确的方向开始。

在哪里可以提出关于 Triton 和 Triton 后端的一般性问题?#

请务必阅读下面的所有信息以及主 Triton 文档,这些文档可在主 server 仓库中找到。如果您在那里找不到答案,您可以在主 Triton issues 页面上提问。

在哪里可以找到 Triton 的所有可用后端?#

任何人都可以开发 Triton 后端,因此我们不可能了解所有可用的后端。但是 Triton 项目确实提供了一组受支持的后端,这些后端经过测试并在每个 Triton 版本中更新。

TensorRT:TensorRT 后端用于执行 TensorRT 模型。tensorrt_backend 仓库包含后端的源代码。

ONNX Runtime:ONNX Runtime 后端用于执行 ONNX 模型。onnxruntime_backend 仓库包含后端的文档和源代码。

TensorFlow:TensorFlow 后端用于执行 GraphDef 和 SavedModel 格式的 TensorFlow 模型。同一个后端用于执行 TensorFlow 1 和 TensorFlow 2 模型。tensorflow_backend 仓库包含后端的文档和源代码。

PyTorch:PyTorch 后端用于执行 TorchScript 和 PyTorch 2.0 格式的 PyTorch 模型。pytorch_backend 仓库包含后端的文档和源代码。

OpenVINO:OpenVINO 后端用于执行 OpenVINO 模型。openvino_backend 仓库包含后端的文档和源代码。

Python:Python 后端允许您用 Python 编写模型逻辑。例如,您可以使用此后端执行用 Python 编写的预处理/后处理代码,或者直接执行 PyTorch Python 脚本(而不是先将其转换为 TorchScript,然后使用 PyTorch 后端)。python_backend 仓库包含后端的文档和源代码。

DALIDALI 是高度优化的构建块集合和一个执行引擎,可加速深度学习应用程序的输入数据预处理。DALI 后端允许您在 Triton 中执行 DALI 管道。dali_backend 仓库包含后端的文档和源代码。

FIL:FIL(Forest Inference Library)后端用于执行各种基于树的 ML 模型,包括 XGBoost 模型、LightGBM 模型、Scikit-Learn 随机森林模型和 cuML 随机森林模型。fil_backend 仓库包含后端的文档和源代码。

TensorRT-LLM:TensorRT-LLM 后端允许您使用 Triton 服务器提供 TensorRT-LLM 模型。请查看 Triton TRT-LLM 用户指南 以获取更多信息。tensorrtllm_backend 仓库包含后端的文档和源代码。

vLLM:vLLM 后端旨在在 vLLM 引擎上运行 受支持的模型。此后端依赖 python_backend 来加载和服务模型。vllm_backend 仓库包含后端的文档和源代码。

重要提示! 并非所有上述后端都在 Triton 支持的每个平台上都受支持。请查看 后端-平台支持矩阵 以了解相关信息。

如何开发自己的 Triton 后端?#

首先,您可能想在主 Triton issues 页面上提问,以确保您没有重复已经存在的后端。然后按照 教程 学习如何创建您的第一个简单的 Triton 后端,并逐步改进它以添加更多功能。您还应该阅读有关 Triton 后端的完整文档。

是否可以将后端添加到现有的 Triton 安装中(或从中删除)?#

是的。请参阅 后端共享库,了解有关 Triton 如何管理实现后端的共享库的一般信息,以及 带有不受支持和自定义后端的 Triton,了解有关如何将您的后端添加到已发布的 Triton Docker 镜像的文档。对于标准安装,全局可用的后端位于 /opt/tritonserver/backends 中。

使用“旧版自定义后端” API 开发的后端呢?#

旧版自定义 API 已从 Triton 中删除。如果您有使用此旧 API 开发的自定义后端,则必须将它们移植到新的 Triton 后端 API

后端#

Triton 后端是执行模型的实现。后端可以是深度学习框架(如 PyTorch、TensorFlow、TensorRT、ONNX Runtime 或 OpenVINO)的包装器。后端也可以实现您想要的任何功能,只要它符合 后端 API 即可。Triton 使用此 API 将请求发送到后端以执行,后端使用该 API 与 Triton 通信。

每个模型都必须与后端关联。模型的后端在模型的配置中使用 backend 设置指定。对于使用 TensorRT 后端,此设置的值应为 tensorrt。同样,对于使用 PyTorch、ONNX 和 TensorFlow 后端,backend 字段应分别设置为 pytorchonnxruntimetensorflow。对于所有其他后端,backend 必须设置为后端的名称。某些后端可能还会检查 platform 设置以对模型进行分类,例如,在 TensorFlow 后端中,platform 应根据模型格式设置为 tensorflow_savedmodeltensorflow_graphdef。请参阅特定的后端仓库,了解是否使用了 platform

后端共享库#

每个后端都必须实现为共享库,并且共享库的名称必须为 libtriton_<backend-name>.so。例如,如果后端的名称为“mybackend”,则模型通过将模型配置“backend”设置设置为“mybackend”来指示它使用该后端,而 Triton 会查找 libtriton_mybackend.so 作为实现该后端的共享库。教程 展示了如何将后端逻辑构建到适当的共享库中的示例。

对于指定后端 B 的模型 M,Triton 按以下顺序在以下位置搜索后端共享库

  • <model_repository>/M/<version_directory>/libtriton_B.so

  • <model_repository>/M/libtriton_B.so

  • <global_backend_directory>/B/libtriton_B.so

其中 <global_backend_directory> 默认情况下为 /opt/tritonserver/backends。可以使用 –backend-directory 标志覆盖默认值。

通常,您会将后端安装到全局后端目录中。例如,如果使用 Triton Docker 镜像,您可以按照 带有不受支持和自定义后端的 Triton 中的说明进行操作。继续以名为“mybackend”的后端为例,您将按如下方式安装到 Triton 镜像中

/opt/
  tritonserver/
    backends/
      mybackend/
        libtriton_mybackend.so
        ... # other files needed by mybackend

从 24.01 开始,可以通过在模型配置中提供 runtime 设置来更改默认后端共享库名称。例如,

runtime: "my_backend_shared_library_name.so"

模型可以选择后端提供的特定运行时实现。

Triton 后端 API#

Triton 后端必须实现 tritonbackend.h 中定义的 C 接口。API 使用以下抽象。

TRITONBACKEND_Backend#

TRITONBACKEND_Backend 对象表示后端本身。同一个后端对象在所有使用该后端的模型之间共享。关联的 API(如 TRITONBACKEND_BackendName)用于获取有关后端的信息,并将用户定义的状态与后端关联。

后端可以选择实现 TRITONBACKEND_Initialize 和 TRITONBACKEND_Finalize,以获取后端对象何时创建和销毁的通知(有关更多信息,请参阅 后端生命周期)。

TRITONBACKEND_Model#

TRITONBACKEND_Model 对象表示模型。Triton 加载的每个模型都与一个 TRITONBACKEND_Model 关联。每个模型都可以使用 TRITONBACKEND_ModelBackend API 来获取表示模型所用后端的后端对象。

同一个模型对象在模型的所有实例之间共享。关联的 API(如 TRITONBACKEND_ModelName)用于获取有关模型的信息,并将用户定义的状态与模型关联。

大多数后端将实现 TRITONBACKEND_ModelInitialize 和 TRITONBACKEND_ModelFinalize,以初始化给定模型的后端,并管理与模型关联的用户定义的状态(有关更多信息,请参阅 后端生命周期)。

后端在实现 TRITONBACKEND_ModelInitialize 和 TRITONBACKEND_ModelFinalize 时必须考虑线程问题。对于给定的模型,Triton 不会对这些函数执行多次同步调用;但是,如果多个模型使用后端,则 Triton 可能会为每个模型同时使用不同的线程调用这些函数。因此,后端必须能够处理对这些函数的多次同步调用。后端实现的最佳实践是在这些函数中仅使用函数本地和模型特定的用户定义状态,如 教程 中所示。

TRITONBACKEND_ModelInstance#

TRITONBACKEND_ModelInstance 对象表示模型实例。Triton 根据模型配置中指定的 instance_group 设置创建一个或多个模型实例。这些实例中的每个实例都与一个 TRITONBACKEND_ModelInstance 对象关联。

后端必须实现的唯一函数是 TRITONBACKEND_ModelInstanceExecute。TRITONBACKEND_ModelInstanceExecute 函数由 Triton 调用,以对一批推理请求执行推理/计算。大多数后端还将实现 TRITONBACKEND_ModelInstanceInitialize 和 TRITONBACKEND_ModelInstanceFinalize,以初始化给定模型实例的后端,并管理与模型关联的用户定义的状态(有关更多信息,请参阅 后端生命周期)。

后端在实现 TRITONBACKEND_ModelInstanceInitialize、TRITONBACKEND_ModelInstanceFinalize 和 TRITONBACKEND_ModelInstanceExecute 时必须考虑线程问题。对于给定的模型实例,Triton 不会对这些函数执行多次同步调用;但是,如果模型具有多个实例或多个模型使用后端,则 Triton 可能会为每个模型实例同时使用不同的线程调用这些函数。因此,后端必须能够处理对这些函数的多次同步调用。后端实现的最佳实践是在这些函数中仅使用函数本地和模型特定的用户定义状态,如 教程 中所示。

TRITONBACKEND_Request#

TRITONBACKEND_Request 对象表示向模型发出的推理请求。后端在 TRITONBACKEND_ModelInstanceExecute 中获取请求对象的所有权,并且必须通过调用 TRITONBACKEND_RequestRelease 来释放每个请求。但是,如果 TRITONBACKEND_ModelInstanceExecute 返回错误,则请求对象的所有权将返回给 Triton。有关请求生命周期的更多信息,请参阅 推理请求和响应

Triton 后端 API 允许后端获取有关请求的信息以及请求的输入和请求输出张量。每个请求输入都由一个 TRITONBACKEND_Input 对象表示。

TRITONBACKEND_Response#

TRITONBACKEND_Response 对象表示后端为特定请求发送的响应。后端使用响应 API 设置响应中包含的每个输出张量的名称、形状、数据类型和张量值。响应可以指示请求失败或成功。有关请求-响应生命周期的更多信息,请参阅 推理请求和响应

TRITONBACKEND_BackendAttribute#

TRITONBACKEND_BackendAttribute 允许后端设置某些属性,Triton 会查询这些属性以告知某些功能支持、首选配置和其他类型的后端特定行为。

初始化后端时,如果后端实现了 TRITONBACKEND_GetBackendAttribute 函数,Triton 将查询该函数。此函数是可选的,但通常用于调用相关的 TRITONBACKEND_BackendAttribute API 来设置后端特定属性。

下面列出了一些相关的 BackendAttribute 设置器 API

  • TRITONBACKEND_BackendSetExecutionPolicy

  • TRITONBACKEND_BackendAttributeAddPreferredInstanceGroup

    • 定义此后端的实例组优先级列表,如果模型配置未显式定义任何实例组,则首选此列表。

  • TRITONBACKEND_BackendAttributeSetParallelModelInstanceLoading

    • 定义后端是否可以安全地处理对 TRITONBACKEND_ModelInstanceInitialize 的并发调用。

    • 并行加载模型实例可以缩短大型实例计数的服务器启动时间。

    • 默认情况下,此属性设置为 false,这意味着除非显式启用,否则所有后端都禁用并行实例加载。

    • 以下官方后端当前支持并行加载模型实例

      • Python

      • ONNXRuntime

完整的 TRITONBACKEND_BackendAttribute 相关 API 列表在 tritonbackend.h 中定义。

后端生命周期#

后端必须仔细管理后端本身、使用后端的模型和模型实例以及使用后端在模型实例上执行的推理请求的生命周期。

后端和模型#

当 Triton 加载模型时,会触发后端、模型和模型实例初始化。

  • 如果模型需要尚未由已加载模型使用的后端,则

    • Triton 加载共享库,该库实现模型所需的后端。

    • Triton 创建 TRITONBACKEND_Backend 对象,该对象表示后端。

    • 如果 TRITONBACKEND_Initialize 在后端共享库中实现,则 Triton 调用它。TRITONBACKEND_Initialize 应在后端完全初始化后才返回。如果 TRITONBACKEND_Initialize 返回错误,Triton 将报告模型加载失败。

  • Triton 创建 TRITONBACKEND_Model 对象,该对象表示模型。如果 TRITONBACKEND_ModelInitialize 在后端共享库中实现,则 Triton 调用它。TRITONBACKEND_ModelInitialize 应在模型的后端完全初始化后才返回。如果 TRITONBACKEND_ModelInitialize 返回错误,Triton 将显示模型加载失败。

  • 对于模型配置中为模型指定的每个模型实例

    • Triton 创建 TRITONBACKEND_ModelInstance 对象,该对象表示模型实例。

    • 如果 TRITONBACKEND_ModelInstanceInitialize 在后端共享库中实现,则 Triton 调用它。TRITONBACKEND_ModelInstanceInitialize 应在实例的后端完全初始化后才返回。如果 TRITONBACKEND_ModelInstanceInitialize 返回错误,Triton 将显示模型加载失败。

当 Triton 卸载模型时,会触发后端、模型和模型实例的最终化。

  • 对于每个模型实例

    • 如果 TRITONBACKEND_ModelInstanceFinalize 在后端共享库中实现,则 Triton 调用它。TRITONBACKEND_ModelInstanceFinalize 应在后端完全最终化后才返回,包括停止为模型实例创建的任何线程并释放为模型实例创建的任何用户定义的状态。

    • Triton 销毁 TRITONBACKEND_ModelInstance 对象,该对象表示模型实例。

  • 如果 TRITONBACKEND_ModelFinalize 在后端共享库中实现,则 Triton 调用它。TRITONBACKEND_ModelFinalize 应在后端完全最终化后才返回,包括停止为模型创建的任何线程并释放为模型创建的任何用户定义的状态。

  • Triton 销毁 TRITONBACKEND_Model 对象,该对象表示模型。

  • 即使没有其他加载的模型需要后端,Triton 也不会最终化和卸载后端,直到 tritonserver 进程退出。当 tritonserver 进程退出时

    • 如果 TRITONBACKEND_Finalize 在后端共享库中实现,则 Triton 调用它。TRITONBACKEND_ModelFinalize 应在后端完全最终化后才返回,包括停止为后端创建的任何线程并释放为后端创建的任何用户定义的状态。

    • Triton 销毁 TRITONBACKEND_Backend 对象,该对象表示后端。

推理请求和响应#

Triton 调用 TRITONBACKEND_ModelInstanceExecute 以在模型实例上执行推理请求。每次调用 TRITONBACKEND_ModelInstanceExecute 都会传递一批要执行的请求以及应使用的模型实例来执行这些请求。后端不应允许调用线程从 TRITONBACKEND_ModelInstanceExecute 返回,直到该实例准备好处理另一组请求。通常,这意味着 TRITONBACKEND_ModelInstanceExecute 函数将在返回之前创建响应并释放请求。但是,如果 TRITONBACKEND_ModelInstanceExecute 返回错误,则请求的所有权将转移回 Triton,然后 Triton 将负责释放它们。因此,在 TRITONBACKEND_ModelInstanceExecute 返回错误的情况下,后端不得保留对请求的引用或以任何方式访问它们。有关请求/响应生命周期的更详细描述,请研究 tritonbackend.h 中 TRITONBACKEND_ModelInstanceExecute 的文档。

单个响应#

大多数后端将为每个请求创建一个响应。对于此类后端,执行单个推理请求需要以下步骤

  • 使用 TRITONBACKEND_ResponseNew 为请求创建响应。

  • 对于每个请求输入张量,使用 TRITONBACKEND_InputProperties 获取输入的形状和数据类型以及包含张量内容的缓冲区。

  • 对于请求期望返回的每个输出张量,使用 TRITONBACKEND_ResponseOutput 创建所需数据类型和形状的输出张量。使用 TRITONBACKEND_OutputBuffer 获取应在其中写入张量内容的缓冲区的指针。

  • 使用输入执行推理计算,将请求的输出张量内容生成到相应的输出缓冲区中。

  • 可选地在响应中设置参数。

  • 使用 TRITONBACKEND_ResponseSend 发送响应。

  • 使用 TRITONBACKEND_RequestRelease 释放请求。

对于一批请求,后端应尝试尽可能地组合执行各个请求,以提高性能。

解耦响应#

后端也可以为请求发送多个响应。后端还可以相对于执行请求批次的顺序,无序发送响应。此类后端称为解耦后端。

解耦后端每个请求使用一个 ResponseFactory 对象来创建和发送任意数量的请求响应。它们必须为每个请求至少发送一个最终响应(即使它只是一个仅标志响应)。您可以使用 TRITONBACKEND_ResponseFactorySendFlags 发送仅标志响应。对于此类后端,执行单个推理请求通常需要以下步骤

  1. 对于每个请求输入张量,使用 TRITONBACKEND_InputProperties 获取输入的形状和数据类型以及包含张量内容的缓冲区。

  2. 使用 TRITONBACKEND_ResponseFactoryNew 为请求创建 ResponseFactory 对象。

  3. 使用 TRITONBACKEND_ResponseNewFromFactory 从 ResponseFactory 对象创建响应。只要您拥有 ResponseFactory 对象,您就可以继续创建响应。

  4. 对于请求期望返回的每个输出张量,使用 TRITONBACKEND_ResponseOutput 创建所需数据类型和形状的输出张量。使用 TRITONBACKEND_OutputBuffer 获取应在其中写入张量内容的缓冲区的指针。

  5. 使用输入执行推理计算,将请求的输出张量内容生成到相应的输出缓冲区中。

  6. 可选地在响应中设置参数。

  7. 使用 TRITONBACKEND_ResponseSend 发送响应。

  8. 重复步骤 3-7,直到没有更多响应。

  9. 使用 TRIONBACKEND_ResponseSend 和 TRITONSERVER_ResponseCompleteFlag 发送请求的最后一个响应,或者在使用 TRITONBACKEND_ResponseFactorySendFlags 发送请求的所有响应后发送。每个请求都需要这样做。

  10. 使用 TRITONBACKEND_RequestRelease 释放请求。

特殊情况#

解耦 API 功能强大,支持各种特殊情况

  • 模型还可以无序发送响应,而不是接收请求的顺序。

  • 如果请求在完全使用内容以生成响应之前被释放,则后端可以复制出输入缓冲区的内容。复制后,可以在退出 TRITONBACKEND_ModelInstanceExecute 之前的任何时间释放请求。副本和 ResponseFactory 对象可以传递到后端中的单独线程。这意味着主调用线程可以从 TRITONBACKEND_ModelInstanceExecute 退出,并且后端只要持有 ResponseFactory 对象,就可以继续生成响应。

repeat 示例 演示了可以从解耦 API 实现的全部功能。

请研究 tritonbackend.h 中这些 TRITONBACKEND_* 函数的文档,以获取有关这些 API 的更多详细信息。阅读 解耦后端和模型,以获取有关如何托管解耦模型的更多详细信息。

构建后端实用程序#

此仓库中的源代码构建到一个“后端实用程序”库中,该库在构建后端时很有用。您无需使用这些实用程序,但它们对大多数后端都很有帮助。

通常,您不需要直接构建此仓库,而是可以将其包含在后端的构建中,如 教程示例 的 CMakeLists.txt 文件中所示。

要在本地目录中构建和安装,请使用以下命令。

$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX:PATH=`pwd`/install ..
$ make install

以下必需的 Triton 仓库将被拉取并在构建中使用。默认情况下,“main”分支/标签将用于每个仓库,但可以使用列出的 CMake 参数来覆盖。

  • triton-inference-server/common: -DTRITON_COMMON_REPO_TAG=[tag]

  • triton-inference-server/core: -DTRITON_CORE_REPO_TAG=[tag]

有关其他构建选项,请参阅 CMakeLists.txt 文件。

基于 Python 的后端#

Triton 还提供了一个选项来创建 基于 Python 的后端。这些后端应实现 TritonPythonModel 接口,该接口可以作为多个模型的后端重用。虽然唯一必需的函数是 execute,但您可能会发现添加 initializefinalize 和任何其他辅助函数有助于增强您的实现。有关示例,请参阅 vLLM 后端,该后端提供了一个通用的 python 脚本来服务 vLLM 支持的模型。