License

Triton 客户端库和示例#

为了简化与 Triton 的通信,Triton 项目提供了几个客户端库以及如何使用这些库的示例。在 Triton 主 问题页面 中提问或报告问题。

提供的客户端库包括

  • C++ 和 Python API,使您可以轻松地从 C++ 或 Python 应用程序与 Triton 通信。使用这些库,您可以向 Triton 发送 HTTP/REST 或 GRPC 请求,以访问其所有功能:推理、状态和健康状况、统计信息和指标、模型仓库管理等。这些库还支持使用系统和 CUDA 共享内存来传递输入到 Triton 和从 Triton 接收输出。

  • Java API(由 阿里云 PAI 团队 贡献),使您可以轻松地从 Java 应用程序使用 HTTP/REST 请求与 Triton 通信。目前,仅支持有限的功能子集。

  • protoc 编译器 可以生成多种编程语言的 GRPC API。

还有许多示例应用程序展示了如何使用这些库。许多这些示例使用来自 示例模型仓库 的模型。

  • image_client 的 C++ 和 Python 版本,这是一个示例应用程序,它使用 C++ 或 Python 客户端库在 Triton 上执行图像分类模型。请参阅 图像分类示例

  • 几个简单的 C++ 示例 展示了如何使用 C++ 库与 Triton 通信以执行推理和其他任务。演示 HTTP/REST 客户端的 C++ 示例以 simple_http_ 为前缀命名,演示 GRPC 客户端的示例以 simple_grpc_ 为前缀命名。请参阅 简单示例应用程序

  • 几个简单的 Python 示例 展示了如何使用 Python 库与 Triton 通信以执行推理和其他任务。演示 HTTP/REST 客户端的 Python 示例以 simple_http_ 为前缀命名,演示 GRPC 客户端的示例以 simple_grpc_ 为前缀命名。请参阅 简单示例应用程序

  • 几个简单的 Java 示例 展示了如何使用 Java API 与 Triton 通信以执行推理和其他任务。

  • 一些 Python 示例,这些示例使用由 protoc 编译器 生成的 Python GRPC API 与 Triton 通信。grpc_client.py 是一个简单的示例,展示了简单的 API 用法。grpc_image_client.py 在功能上与 image_client 等效,但它使用生成的 GRPC 客户端存根与 Triton 通信。

获取客户端库和示例#

获取 Python 客户端库的最简单方法是 使用 pip 安装 tritonclient 模块。您还可以从 Triton GitHub 发布版本 下载 C++、Python 和 Java 客户端库,或者从 NGC 下载包含客户端库的预构建 Docker 镜像NVIDIA GPU Cloud (NGC)

也可以使用 cmake 构建客户端库。

使用 Python 包安装程序 (pip) 下载#

GRPC 和 HTTP 客户端库作为 Python 包提供,可以使用最新版本的 pip 安装。

$ pip install tritonclient[all]

使用 all 会同时安装 HTTP/REST 和 GRPC 客户端库。有两个可选包可用,grpchttp,可用于专门安装对协议的支持。例如,要仅安装 HTTP/REST 客户端库,请使用:

$ pip install tritonclient[http]

还有另一个可选包,即 cuda,必须安装该包才能使用 cuda_shared_memory 实用程序。all 规范默认将安装 cuda 包,但在其他情况下,需要显式指定 cuda 以安装支持 cuda_shared_memory 的客户端。

$ pip install tritonclient[http, cuda]

安装包的组件包括

  • http

  • grpc [ service_pb2, service_pb2_grpc, model_config_pb2 ]

  • utils [ Linux 发行版将包含 shared_memorycuda_shared_memory]

从 GitHub 下载#

可以从与您感兴趣的版本对应的 Triton GitHub 发布页面 下载客户端库。客户端库位于发布页面的“Assets”部分,在一个以发布版本和操作系统命名的 tar 文件中,例如,v2.3.0_ubuntu2004.clients.tar.gz。

预构建的库可以在相应的宿主机系统上使用,或者您可以将它们安装到 Triton 容器中,以便在同一容器中同时拥有客户端和服务器。

$ mkdir clients
$ cd clients
$ wget https://github.com/triton-inference-server/server/releases/download/<tarfile_path>
$ tar xzf <tarfile_name>

安装后,库可以在 lib/ 中找到,头文件在 include/ 中,Python wheel 文件在 python/ 中,jar 文件在 java/ 中。bin/ 和 python/ 目录包含已构建的示例,您可以在下面了解更多信息。

从 NGC 下载 Docker 镜像#

包含客户端库和示例的 Docker 镜像可从 NVIDIA GPU Cloud (NGC) 获取。在尝试拉取容器之前,请确保您有权访问 NGC。有关分步说明,请参阅 NGC 入门指南

使用 docker pull 从 NGC 获取客户端库和示例容器。

$ docker pull nvcr.io/nvidia/tritonserver:<xx.yy>-py3-sdk

其中 <xx.yy> 是您要拉取的版本。在容器内,客户端库位于 /workspace/install/lib 中,相应的头文件位于 /workspace/install/include 中,Python wheel 文件位于 /workspace/install/python 中。镜像还将包含已构建的客户端示例。

重要提示: 当使用 Docker 容器运行服务器或客户端并使用 CUDA 共享内存功能 时,您需要在启动容器时添加 --pid host 标志。原因是 CUDA IPC API 要求导出的指针的源和目标的 PID 不同。否则,Docker 启用 PID 命名空间可能会导致源和目标 PID 相等。当两个容器都以非交互模式启动时,将始终观察到该错误。

使用 CMake 构建#

客户端库构建是使用 CMake 执行的。要构建具有所有功能的客户端库和示例,请首先将目录更改为此仓库的根目录,并检出您要构建的分支的发布版本(如果您要构建正在开发中的版本,则检出 main 分支)。

$ git checkout main

如果构建 Java 客户端,您必须首先安装 Maven 和适用于您操作系统的 JDK。例如,对于 Ubuntu,您应该安装 default-jdk

$ apt-get install default-jdk maven

在 Windows 与非 Windows 上构建需要不同的调用,因为 Windows 上的 Triton 尚不支持所有构建选项。

非 Windows#

使用 cmake 配置构建。您应该根据您正在使用的 Triton 客户端组件以及您想要构建的组件来调整标志。

如果您正在发布分支上构建(或基于发布分支的开发分支上构建),则还必须使用额外的 cmake 参数来指向客户端构建所依赖的仓库的该发布分支。例如,如果您正在构建 r21.10 客户端分支,则需要使用以下额外的 cmake 标志

-DTRITON_COMMON_REPO_TAG=r21.10
-DTRITON_THIRD_PARTY_REPO_TAG=r21.10
-DTRITON_CORE_REPO_TAG=r21.10

然后使用 make 构建客户端和示例。

$ make cc-clients python-clients java-clients

构建完成后,库和示例可以在 install 目录中找到。

Windows#

要构建客户端,您必须安装适当的 C++ 编译器和构建所需的其他依赖项。最简单的方法是创建 Windows min Docker 镜像 并在从该镜像启动的容器中执行构建。

> docker run  -it --rm win10-py3-min powershell

对于构建,没有必要使用 Docker 或 win10-py3-min 容器,但如果您不使用,则必须将适当的依赖项安装到您的宿主机系统上。

接下来,使用 cmake 配置构建。如果您不是在 win10-py3-min 容器中构建,那么您可能需要调整以下命令中的 CMAKE_TOOLCHAIN_FILE 位置。

$ mkdir build
$ cd build
$ cmake -DVCPKG_TARGET_TRIPLET=x64-windows -DCMAKE_TOOLCHAIN_FILE='/vcpkg/scripts/buildsystems/vcpkg.cmake' -DCMAKE_INSTALL_PREFIX=install -DTRITON_ENABLE_CC_GRPC=ON -DTRITON_ENABLE_PYTHON_GRPC=ON -DTRITON_ENABLE_GPU=OFF -DTRITON_ENABLE_EXAMPLES=ON -DTRITON_ENABLE_TESTS=ON ..

如果您正在发布分支上构建(或基于发布分支的开发分支上构建),则还必须使用额外的 cmake 参数来指向客户端构建所依赖的仓库的该发布分支。例如,如果您正在构建 r21.10 客户端分支,则需要使用以下额外的 cmake 标志

-DTRITON_COMMON_REPO_TAG=r21.10
-DTRITON_THIRD_PARTY_REPO_TAG=r21.10
-DTRITON_CORE_REPO_TAG=r21.10

然后使用 msbuild.exe 进行构建。

$ msbuild.exe cc-clients.vcxproj -p:Configuration=Release -clp:ErrorsOnly
$ msbuild.exe python-clients.vcxproj -p:Configuration=Release -clp:ErrorsOnly

构建完成后,库和示例可以在 install 目录中找到。

客户端库 API#

C++ 客户端 API 公开了一个基于类的接口。注释接口在 grpc_client.hhttp_client.hcommon.h 中提供。

Python 客户端 API 提供了与 C++ API 类似的功能。注释接口在 grpchttp 中提供。

Java 客户端 API 提供了与 Python API 类似的功能,具有类似的类和方法。有关更多信息,请参阅 Java 客户端目录

HTTP 选项#

SSL/TLS#

客户端库允许使用 HTTPS 协议通过安全通道进行通信。仅设置这些 SSL 选项并不能确保安全通信。Triton 服务器应在 https:// 代理(例如 nginx)后面运行。然后,客户端可以与代理建立安全通道。服务器仓库中的 qa/L0_https 演示了如何实现这一点。

对于 C++ 客户端,请参阅 HttpSslOptions 结构,该结构在 http_client.h 中封装了这些选项。

对于 Python 客户端,请在 http/__init__.py 中查找以下选项

  • ssl

  • ssl_options

  • ssl_context_factory

  • insecure

C++Python 示例演示了如何在客户端使用 SSL/TLS 设置。

压缩#

客户端库为 HTTP 事务启用在线压缩。

对于 C++ 客户端,请参阅 http_client.hInferAsyncInfer 函数中的 request_compression_algorithmresponse_compression_algorithm 参数。默认情况下,该参数设置为 CompressionType::NONE

类似地,对于 Python 客户端,请参阅 http/__init__.pyinferasync_infer 函数中的 request_compression_algorithmresponse_compression_algorithm 参数。

C++Python 示例演示了如何使用压缩选项。

Python AsyncIO 支持(Beta 版)#

此功能目前处于 Beta 版,可能会发生更改。

高级用户可以通过 asyncawait 语法调用 Python 客户端。infer 示例演示了如何使用 AsyncIO 进行推理。

如果将 SSL/TLS 与 AsyncIO 结合使用,请在 http/aio/__init__.py 中查找 sslssl_context 选项

Python 客户端插件 API(Beta 版)#

此功能目前处于 Beta 版,可能会发生更改。

Triton 客户端插件 API 允许您注册自定义插件以添加或修改请求标头。如果您在 Triton 服务器前面有网关,该网关需要每个请求的额外标头(例如 HTTP 授权),这将非常有用。通过注册插件,您的网关将与 Python 客户端一起工作,而无需额外的配置。请注意,Triton 服务器不实现身份验证或授权机制,同样,Triton 服务器也不是额外标头的直接使用者。

插件必须实现 __call__ 方法。__call__ 方法的签名应如下所示

class MyPlugin:
  def __call__(self, request):
       """This method will be called for every HTTP request. Currently, the only
       field that can be accessed by the request object is the `request.headers`
       field. This field must be updated in-place.
       """
       request.headers['my-header-key'] = 'my-header-value'

插件实现完成后,您可以通过在 InferenceServerClient 对象上调用 register 来注册插件。

from tritonclient.http import InferenceServerClient

client = InferenceServerClient(...)

# Register the plugin
my_plugin = MyPlugin()
client.register_plugin(my_plugin)

# All the method calls will update the headers according to the plugin
# implementation.
client.infer(...)

要注销插件,您可以调用 client.unregister_plugin() 函数。

基本身份验证#

您可以注册实现 基本身份验证BasicAuth 插件。

from tritonclient.grpc.auth import BasicAuth
from tritonclient.grpc import InferenceServerClient

basic_auth = BasicAuth('username', 'password')
client = InferenceServerClient('...')

client.register_plugin(basic_auth)

上面的示例显示了如何为 gRPC 客户端注册插件。BasicAuth 插件可以为 HTTP 和 AsyncIO 客户端进行类似地注册。

GRPC 选项#

SSL/TLS#

客户端库允许使用 gRPC 协议通过安全通道进行通信。

对于 C++ 客户端,请参阅 SslOptions 结构,该结构在 grpc_client.h 中封装了这些选项。

对于 Python 客户端,请在 grpc/__init__.py 中查找以下选项

  • ssl

  • root_certificates

  • private_key

  • certificate_chain

C++Python 示例演示了如何在客户端使用 SSL/TLS 设置。有关相应的服务器端参数的信息,请参阅 服务器文档

压缩#

客户端库还公开了用于 gRPC 事务的在线压缩选项。

对于 C++ 客户端,请参阅 grpc_client.hInferAsyncInferStartStream 函数中的 compression_algorithm 参数。默认情况下,该参数设置为 GRPC_COMPRESS_NONE

类似地,对于 Python 客户端,请参阅 grpc/__init__.pyinferasync_inferstart_stream 函数中的 compression_algorithm 参数。

C++Python 示例演示了如何为客户端配置压缩。有关相应的服务器端参数的信息,请参阅 服务器文档

GRPC KeepAlive#

Triton 公开了 GRPC KeepAlive 参数,客户端和服务器的默认值在 此处 描述。

您可以在 C++Python 客户端库中找到封装这些参数的 KeepAliveOptions 结构/类。

还有一个 C++Python 示例,演示了如何在客户端设置这些参数。有关相应的服务器端参数的信息,请参阅 服务器文档

自定义 GRPC 通道参数#

高级用户可能需要特定的客户端 GRPC 通道参数,这些参数目前 Triton 没有通过直接方式公开。为了支持这一点,Triton 允许用户在创建 GRPC 客户端时传递自定义通道参数。当使用此选项时,用户有责任传递适用于其用例的有效参数组合;Triton 无法切实测试每种可能的通道参数组合。

有一个 C++Python 示例,演示了如何在创建 GRPC 客户端时构造和传递这些自定义参数。

您可以在 此处 找到可能的 GRPC 通道参数的完整列表。

Python AsyncIO 支持(Beta 版)#

此功能目前处于 Beta 版,可能会发生更改。

高级用户可以通过 asyncawait 语法调用 Python 客户端。inferstream 示例演示了如何使用 AsyncIO 进行推理。

请求取消#

从 r23.10 开始,triton python gRPC 客户端可以向正在进行的请求发出取消。这可以通过在 async_infer() API 返回的 CallContext 对象上调用 cancel() 来完成。

  ctx = client.async_infer(...)
  ctx.cancel()

对于流式请求,可以将 cancel_requests=True 发送到 stop_stream() API,以终止通过此流发送的所有正在进行的请求。

  client.start_stream()
  for _ in range(10):
    client.async_stream_infer(...)

  # Cancels all pending requests on stream closure rather than blocking until requests complete
  client.stop_stream(cancel_requests=True)

有关这些 API 的更多详细信息,请参阅 grpc/_client.py

对于 gRPC AsyncIO 请求,可以安全地取消包装 infer() 协程的 AsyncIO 任务。

  infer_task = asyncio.create_task(aio_client.infer(...))
  infer_task.cancel()

对于 gRPC AsyncIO 流式请求,可以在 stream_infer() API 返回的异步迭代器上调用 cancel()

  responses_iterator = aio_client.stream_infer(...)
  responses_iterator.cancel()

有关这些 API 的更多详细信息,请参阅 grpc/aio/_init_.py

有关服务器端如何处理此问题的更多信息,请参阅服务器用户指南中的 request_cancellation。如果您使用您选择的语言编写自己的 gRPC 客户端,请查阅 gRPC 指南中的 取消

GRPC 状态码#

从 24.08 版本开始,Triton 服务器为所有客户端的流模式引入了 gRPC 错误代码支持,从而增强了错误报告功能。启用此功能后,Triton 服务器将返回标准 gRPC 错误代码,并在传递错误后关闭流。此功能是可选的,可以通过添加带有 triton_grpc_error 键和 true 值的标头来启用。有关服务器端如何处理此问题的更多信息,请参阅服务器中的 grpc 错误代码。有关更多详细信息,请参阅 gRPC 指南中的 状态码。以下是启用此功能的 Python 代码片段。如果没有此标头,Triton 服务器将在默认模式下继续流式传输,并在提供的回调中的 InferenceServerException 对象中返回错误消息和状态。

  triton_client = grpcclient.InferenceServerClient(triton_server_url)
  # New added header key value
  metadata = {"triton_grpc_error": "true"}
  triton_client.start_stream(
    callback=partial(callback, user_data), headers=metadata
  )

简单示例应用程序#

本节介绍几个简单的示例应用程序以及它们说明的功能。

字节/字符串数据类型#

某些框架支持张量,其中张量中的每个元素都是可变长度的二进制数据。每个元素可以保存字符串或任意字节序列。在客户端,此数据类型为 BYTES(有关支持的数据类型的信息,请参阅 数据类型)。

Python 客户端库使用 numpy 来表示输入和输出张量。对于 BYTES 张量,numpy 数组的 dtype 应为 'np.object_',如示例所示。为了向后兼容以前版本的客户端库,'np.bytes_' 也可用于 BYTES 张量。但是,不建议使用 'np.bytes_',因为使用此 dtype 将导致 numpy 从每个数组元素中删除所有尾随零。因此,以零结尾的二进制序列将无法正确表示。

C++ 示例应用程序 simple_http_string_infer_client.cc 和 simple_grpc_string_infer_client.cc 中演示了 BYTES 张量。Python 示例应用程序 simple_http_string_infer_client.py 和 simple_grpc_string_infer_client.py 中演示了字符串张量。

系统共享内存#

在某些情况下,使用系统共享内存来在客户端库和 Triton 之间通信张量可以显着提高性能。

C++ 示例应用程序 simple_http_shm_client.cc 和 simple_grpc_shm_client.cc 演示了如何使用系统共享内存。Python 示例应用程序 simple_http_shm_client.py 和 simple_grpc_shm_client.py 演示了如何使用系统共享内存。

Python 没有分配和访问共享内存的标准方法,因此作为一个示例,提供了一个简单的 系统共享内存模块,该模块可以与 Python 客户端库一起使用,以创建、设置和销毁系统共享内存。

CUDA 共享内存#

在某些情况下,使用 CUDA 共享内存来在客户端库和 Triton 之间传递张量可以显著提高性能。

C++ 示例应用程序 simple_http_cudashm_client.cc 和 simple_grpc_cudashm_client.cc 演示了如何使用 CUDA 共享内存。Python 示例应用程序 simple_http_cudashm_client.py 和 simple_grpc_cudashm_client.py 演示了如何使用 CUDA 共享内存。

Python 没有分配和访问共享内存的标准方法,因此作为一个示例,提供了一个简单的 CUDA 共享内存模块,该模块可以与 Python 客户端库一起使用,以创建、设置和销毁 CUDA 共享内存。该模块目前支持 numpy 数组(示例用法)和 DLPack 张量(示例用法)。

用于有状态模型的客户端 API#

当使用有状态模型执行推理时,客户端必须识别哪些推理请求属于同一序列,以及序列何时开始和结束。

每个序列都使用序列 ID 标识,该 ID 在发出推理请求时提供。创建唯一序列 ID 由客户端负责。对于每个序列,第一个推理请求应标记为序列的开始,最后一个推理请求应标记为序列的结束。

C++ 示例应用程序 simple_grpc_sequence_stream_infer_client.cc 演示了序列 ID 以及开始和结束标志的用法。Python 示例应用程序 simple_grpc_sequence_stream_infer_client.py 演示了序列 ID 以及开始和结束标志的用法。

图像分类示例#

使用 C++ 客户端 API 的图像分类示例位于 src/c++/examples/image_client.cc。Python 版本的图像分类客户端位于 src/python/examples/image_client.py

要使用 image_client(或 image_client.py),您必须首先运行一个 Triton,它正在服务一个或多个图像分类模型。image_client 应用程序要求模型具有单个图像输入并产生单个分类输出。如果您没有包含图像分类模型的模型仓库,请参阅 快速入门 以获取有关如何创建一个的说明。

一旦 Triton 运行,您可以使用 image_client 应用程序发送推理请求。您可以指定单个图像或包含图像的目录。在这里,我们为来自 qa/images 的图像的 inception_graphdef 模型发送请求。

$ image_client -m inception_graphdef -s INCEPTION qa/images/mug.jpg
Request 0, batch size 1
Image 'qa/images/mug.jpg':
    0.754130 (505) = COFFEE MUG

Python 版本的应用程序接受相同的命令行参数。

$ python image_client.py -m inception_graphdef -s INCEPTION qa/images/mug.jpg
Request 0, batch size 1
Image 'qa/images/mug.jpg':
     0.826384 (505) = COFFEE MUG

image_client 和 image_client.py 应用程序使用客户端库与 Triton 通信。默认情况下,image_client 指示客户端库使用 HTTP/REST 协议,但您可以使用 GRPC 协议,方法是提供 -i 标志。您还必须使用 -u 标志指向 Triton 上的 GRPC 端点。

$ image_client -i grpc -u localhost:8001 -m inception_graphdef -s INCEPTION qa/images/mug.jpg
Request 0, batch size 1
Image 'qa/images/mug.jpg':
    0.754130 (505) = COFFEE MUG

默认情况下,客户端打印图像的最可能分类。使用 -c 标志可查看更多分类。

$ image_client -m inception_graphdef -s INCEPTION -c 3 qa/images/mug.jpg
Request 0, batch size 1
Image 'qa/images/mug.jpg':
    0.754130 (505) = COFFEE MUG
    0.157077 (969) = CUP
    0.002880 (968) = ESPRESSO

-b 标志允许您发送一批图像进行推理。image_client 应用程序将从您指定的图像或多个图像中形成批次。如果批次大于图像数量,则 image_client 将只重复图像以填充批次。

$ image_client -m inception_graphdef -s INCEPTION -c 3 -b 2 qa/images/mug.jpg
Request 0, batch size 2
Image 'qa/images/mug.jpg':
    0.754130 (505) = COFFEE MUG
    0.157077 (969) = CUP
    0.002880 (968) = ESPRESSO
Image 'qa/images/mug.jpg':
    0.754130 (505) = COFFEE MUG
    0.157077 (969) = CUP
    0.002880 (968) = ESPRESSO

提供目录而不是单个图像以对目录中的所有图像执行推理。

$ image_client -m inception_graphdef -s INCEPTION -c 3 -b 2 qa/images
Request 0, batch size 2
Image '/opt/tritonserver/qa/images/car.jpg':
    0.819196 (818) = SPORTS CAR
    0.033457 (437) = BEACH WAGON
    0.031232 (480) = CAR WHEEL
Image '/opt/tritonserver/qa/images/mug.jpg':
    0.754130 (505) = COFFEE MUG
    0.157077 (969) = CUP
    0.002880 (968) = ESPRESSO
Request 1, batch size 2
Image '/opt/tritonserver/qa/images/vulture.jpeg':
    0.977632 (24) = VULTURE
    0.000613 (9) = HEN
    0.000560 (137) = EUROPEAN GALLINULE
Image '/opt/tritonserver/qa/images/car.jpg':
    0.819196 (818) = SPORTS CAR
    0.033457 (437) = BEACH WAGON
    0.031232 (480) = CAR WHEEL

grpc_image_client.py 应用程序的行为与 image_client 相同,不同之处在于它没有使用客户端库,而是使用 GRPC 生成的库与 Triton 通信。

集成图像分类示例应用程序#

与上面的图像分类示例相比,此示例使用图像预处理模型的集成,该模型实现为 DALI 后端 和 TensorFlow Inception 模型。集成模型允许您在请求中发送原始图像二进制文件,并接收分类结果,而无需在客户端上预处理图像。

要尝试此示例,您应遵循 DALI 集成示例说明