说明文档
<!--
版权所有 2023, NVIDIA CORPORATION & AFFILIATES. 保留所有权利。
以源代码和二进制形式重新分发和使用,无论是否修改,
均须满足以下条件:
* 源代码的重新分发必须保留上述版权声明、此条件列表和以下免责声明。
* 二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。
* 未经事先书面许可,不得使用 NVIDIA CORPORATION 的名称或其贡献者的名称来认可或推广从本软件衍生的产品。
本软件由版权持有人"按原样"提供,不提供任何明示或暗示的保证,
包括但不限于对适销性和特定用途适用性的暗示保证。
在任何情况下,版权所有者或贡献者均不对任何直接、间接、偶然、特殊、
惩罚性或后果性损害(包括但不限于替代商品或服务的采购、使用、数据或
利润的损失,或业务中断)负责,无论是基于合同、严格责任或侵权
#(包括疏忽或其他)的任何责任理论,即使已被告知此类损害的可能性。 -->
使用 Triton 部署模型
| 导航至 | 第二部分:提高资源利用率 | 文档:模型仓库 | 文档:模型配置 |
|---|
任何深度学习推理服务解决方案都需要解决两个基本挑战:
- 管理多个模型。
- 模型的版本控制、加载和卸载。
开始之前
本概念指南旨在帮助开发者了解在构建用于部署深度学习流水线的推理基础设施时所面临的挑战。本指南的第1部分 - 第5部分旨在解决一个简单问题:部署一个高性能且可扩展的流水线,用于从图像中转录文本。该流水线包括5个步骤:
- 预处理原始图像
- 检测图像中包含文本的区域(文本检测模型)
- 将图像裁剪到包含文本的区域
- 查找文本概率(文本识别模型)
- 将概率转换为实际文本
在第1部分中,我们首先在 Triton 上部署两个模型,前/后处理步骤在客户端完成。
部署多个模型
管理多个模型的关键挑战在于构建一个能够满足不同模型不同需求的基础设施。例如,用户可能需要在同一台服务器上部署 PyTorch 模型和 TensorFlow 模型,并且两个模型有不同的负载,需要在不同硬件设备上运行,还需要独立管理服务配置(模型队列、版本、缓存、加速等)。Triton 推理服务器可以满足以上所有需求以及更多。
使用 Triton 推理服务器部署模型的第一步是构建一个仓库,用于存放将被服务的模型和配置模式。为了演示目的,我们将使用 EAST 模型来检测文本,以及一个文本识别模型。此工作流程主要改编自 OpenCV 的文本检测示例。
首先,让我们克隆仓库并导航到此文件夹。
cd Conceptual_Guide/Part_1-model_deployment
接下来,我们将下载必要的模型并确保它们采用 Triton 可以部署的格式。
模型1:文本检测
下载并解压 OpenCV 的 EAST 模型。
wget https://www.dropbox.com/s/r2ingd0l3zt8hxs/frozen_east_text_detection.tar.gz
tar -xvf frozen_east_text_detection.tar.gz
导出为 ONNX。
注意:以下步骤需要您安装 TensorFlow 库。我们建议在 NGC TensorFlow 容器环境中执行以下步骤,您可以使用
docker run -it --gpus all -v ${PWD}:/workspace nvcr.io/nvidia/tensorflow:<yy.mm>-tf2-py3启动该容器
pip install -U tf2onnx
python -m tf2onnx.convert --input frozen_east_text_detection.pb --inputs \"input_images:0\" --outputs \"feature_fusion/Conv_7/Sigmoid:0\",\"feature_fusion/concat_3:0\" --output detection.onnx
模型2:文本识别
下载文本识别模型权重。
wget https://www.dropbox.com/sh/j3xmli4di1zuv3s/AABzCC1KGbIRe2wRwa3diWKwa/None-ResNet-None-CTC.pth
使用 utils 文件夹中的模型定义文件将模型导出为 .onnx。此文件改编自 Baek et. al. 2019。
注意:以下 Python 脚本需要您安装 PyTorch 库。我们建议在 NGC PyTorch 容器环境中执行以下步骤,您可以使用
docker run -it --gpus all -v ${PWD}:/workspace nvcr.io/nvidia/pytorch:<yy.mm>-py3启动该容器
import torch
from utils.model import STRModel
# 创建 PyTorch 模型对象
model = STRModel(input_channels=1, output_channels=512, num_classes=37)
# 从外部文件加载模型权重
state = torch.load(\"None-ResNet-None-CTC.pth\")
state = {key.replace(\"module.\", \"\"): value for key, value in state.items()}
model.load_state_dict(state)
# 通过追踪模型创建 ONNX 文件
trace_input = torch.randn(1, 1, 32, 100)
torch.onnx.export(model, trace_input, \"str.onnx\", verbose=True)
设置模型仓库
模型仓库是 Triton 读取模型及每个模型相关元数据(配置、版本文件等)的方式。这些模型仓库可以位于本地或网络附加文件系统,也可以位于 AWS S3、Azure Blob Storage 或 Google Cloud Storage 等云对象存储中。有关模型仓库位置的更多详细信息,请参阅文档。服务器也可以使用多个不同的模型仓库。为简单起见,本说明仅使用存储在本地文件系统中的单个仓库,格式如下:
# 示例仓库结构
<model-repository>/
<model-name>/
[config.pbtxt]
[<output-labels-file> ...]
<version>/
<model-definition-file>
<version>/
<model-definition-file>
...
<model-name>/
[config.pbtxt]
[<output-labels-file> ...]
<version>/
<model-definition-file>
<version>/
<model-definition-file>
...
...
上述结构中有三个重要组件需要讨论:
model-name:模型的标识名称。config.pbtxt:对于每个模型,用户可以定义模型配置。此配置至少需要定义:模型输入和输出的后端、名称、形状和数据类型。对于大多数流行的后端,此配置文件会使用默认值自动生成。配置文件的完整规范可在model_configprotobuf 定义中找到。version:版本控制根据所选策略使同一模型的多个版本可供使用。有关版本控制的更多信息。
对于此示例,您可以按以下方式设置模型仓库结构:
mkdir -p model_repository/text_detection/1
mv detection.onnx model_repository/text_detection/1/model.onnx
mkdir -p model_repository/text_recognition/1
mv str.onnx model_repository/text_recognition/1/model.onnx
这些命令应该会为您创建一个如下所示的仓库:
# 预期的文件夹布局
model_repository/
├── text_detection
│ ├── 1
│ │ └── model.onnx
│ └── config.pbtxt
└── text_recognition
├── 1
│ └── model.onnx
└── config.pbtxt
请注意,对于此示例,我们已经创建了 config.pbtxt 文件并将它们放置在必要的位置。在下一节中,我们将讨论这些文件的内容。
模型配置
准备好模型和文件结构后,接下来我们需要查看 config.pbtxt 模型配置文件。让我们首先查看 /model_repository/text_detection/config.pbtxt 中为您提供的 EAST 文本检测 模型的模型配置。这显示 text_detection 是一个 ONNX 模型,它有一个 input 张量和两个 output 张量。
name: \"text_detection\"
backend: \"onnxruntime\"
max_batch_size : 256
input [
{
name: \"input_images:0\"
data_type: TYPE_FP32
dims: [ -1, -1, -1, 3 ]
}
]
output [
{
name: \"feature_fusion/Conv_7/Sigmoid:0\"
data_type: TYPE_FP32
dims: [ -1, -1, -1, 1 ]
}
]
output [
{
name: \"feature_fusion/concat_3:0\"
data_type: TYPE_FP32
dims: [ -1, -1, -1, 5 ]
}
]
name:"name" 是一个可选字段,其值应与模型目录的名称匹配。backend:此字段指示用于运行模型的后端。Triton 支持多种后端,如 TensorFlow、PyTorch、Python、ONNX 等。有关字段选择的完整列表,请参阅这些注释。max_batch_size:顾名思义,此字段定义模型可以支持的最大批次大小。input和output:输入和输出部分指定名称、形状、数据类型等,同时提供重塑等操作和对不规则批次的支持。
在大多数情况下,可以省略 input 和 output 部分,让 Triton 直接从模型文件中提取该信息。在这里,我们为了清晰起见包含了它们,并且因为稍后在客户端应用程序中我们需要知道输出张量的名称。
有关所有支持的字段及其值的详细信息,请参阅模型配置 protobuf 定义文件。
启动服务器
创建好仓库并配置好模型后,我们就可以启动服务器了。虽然 Triton 推理服务器可以从源代码构建,但对于此示例,强烈建议使用 NGC 免费提供的预构建 Docker 容器。
# 将镜像名称中的 yy.mm 替换为所需 Triton 版本的发布年份和月份
# 例如 22.08
docker run --gpus=all -it --shm-size=256m --rm -p8000:8000 -p8001:8001 -p8002:8002 -v $(pwd)/model_repository:/models nvcr.io/nvidia/tritonserver:<yy.mm>-py3
一旦 Triton 推理服务器构建完成或进入容器后,可以使用以下命令启动:
tritonserver --model-repository=/models
这将启动服务器,模型实例将准备好进行推理。
I0712 16:37:18.246487 128 server.cc:626]
+------------------+---------+--------+
| Model | Version | Status |
+------------------+---------+--------+
| text_detection | 1 | READY |
| text_recognition | 1 | READY |
+------------------+---------+--------+
I0712 16:37:18.267625 128 metrics.cc:650] Collecting metrics for GPU 0: NVIDIA GeForce RTX 3090
I0712 16:37:18.268041 128 tritonserver.cc:2159]
+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Option | Value |
+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| server_id | triton |
| server_version | 2.23.0 |
| server_extensions | classification sequence model_repository model_repository(unload_dependents) schedule_policy model_configuration system_shared_memory cuda_shared_memory binary_tensor_data statistics trace |
| model_repository_path[0] | /models |
| model_control_mode | MODE_NONE |
| strict_model_config | 1 |
| rate_limit | OFF |
| pinned_memory_pool_byte_size | 268435456 |
| cuda_memory_pool_byte_size{0} | 67108864 |
| response_cache_byte_size | 0 |
| min_supported_compute_capability | 6.0 |
| strict_readiness | 1 |
| exit_timeout | 30 |
+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
I0712 16:37:18.269464 128 grpc_server.cc:4587] Started GRPCInferenceService at 0.0.0.0:8001
I0712 16:37:18.269956 128 http_server.cc:3303] Started HTTPService at 0.0.0.0:8000
I0712 16:37:18.311686 128 http_server.cc:178] Started Metrics Service at 0.0.0.0:8002
构建客户端应用程序
现在我们的 Triton 服务器已经启动,我们可以开始向它发送消息。与 Triton 推理服务器交互有三种方式:
- HTTP(S) API
- gRPC API
- 原生 C API
还有预构建的客户端库,包括 C++、Python 和 Java,它们封装了 HTTP 和 gRPC API。此示例包含一个 Python 客户端脚本 client.py,它使用 tritonclient python 库通过 HTTP API 与 Triton 通信。
让我们检查此文件的内容:
-
首先,我们从
tritonclient库导入 HTTP 客户端,以及我们将用于处理图像的其他几个库:import math import numpy as np import cv2 import tritonclient.http as httpclient -
接下来,我们将定义一些辅助函数来处理流水线的预处理和后处理步骤。此处省略详细内容以保持简洁,但您可以查看
client.py文件了解更多详情def detection_preprocessing(image: cv2.Mat) -> np.ndarray: ... def detection_postprocessing(scores: np.ndarray, geometry: np.ndarray, preprocessed_image: np.ndarray) -> np.ndarray: ... def recognition_postprocessing(scores: np.ndarray) -> str: ... -
然后,我们创建一个客户端对象,并初始化与 Triton 推理服务器的连接。
client = httpclient.InferenceServerClient(url=\"localhost:8000\") -
现在,我们将从数据创建要发送给 Triton 的
InferInput。raw_image = cv2.imread(\"./img2.jpg\") preprocessed_image = detection_preprocessing(raw_image) detection_input = httpclient.InferInput(\"input_images:0\", preprocessed_image.shape, datatype=\"FP32\") detection_input.set_data_from_numpy(preprocessed_image, binary_data=True) -
最后,我们准备向 Triton 推理服务器发送推理请求并获取响应
detection_response = client.infer(model_name=\"text_detection\", inputs=[detection_input]) -
之后,我们将使用文本识别模型重复此过程,执行下一个处理步骤,创建输入对象,查询服务器,最后执行后处理并打印结果。
# 处理来自检测模型的响应 scores = detection_response.as_numpy('feature_fusion/Conv_7/Sigmoid:0') geometry = detection_response.as_numpy('feature_fusion/concat_3:0') cropped_images = detection_postprocessing(scores, geometry, preprocessed_image) # 为识别模型创建输入对象 recognition_input = httpclient.InferInput(\"input.1\", cropped_images.shape, datatype=\"FP32\") recognition_input.set_data_from_numpy(cropped_images, binary_data=True) # 查询服务器 recognition_response = client.infer(model_name=\"text_recognition\", inputs=[recognition_input]) # 处理来自识别模型的响应 text = recognition_postprocessing(recognition_response.as_numpy('308')) print(text)
让我们试试看!
pip install tritonclient[http] opencv-python-headless
python client.py
您可能已经注意到,检索第一个模型的结果只是为了进行一些处理然后将它们发送回 Triton,这有点冗余。在本教程的第5部分中,我们将探讨如何将更多处理步骤移至服务器并在单次网络调用中执行多个模型。
模型版本控制
部署不同版本模型的能力对于构建 MLOps 流水线至关重要。这种需求源于进行 A/B 测试、轻松回滚模型版本等用例。Triton 用户可以在同一仓库中添加文件夹和新模型:
model_repository/
├── text_detection
│ ├── 1
│ │ └── model.onnx
│ ├── 2
│ │ └── model.onnx
│ └── config.pbtxt
└── text_recognition
├── 1
│ └── model.onnx
└── config.pbtxt
默认情况下,Triton 提供"最新"的模型,但提供不同版本模型的策略是可定制的。有关更多信息,请参阅本指南。
加载和卸载模型
Triton 具有模型管理 API,可用于控制模型加载卸载策略。此 API 在需要在同一服务器上加载或卸载一个或多个模型而不中断其他正在服务的模型推理的情况下非常有用。用户可以从三种控制模式中选择一种:
- NONE
- EXPLICIT
- POLL
tritonserver --model-repository=/models --model-control-mode=poll
这些策略也可以在启动服务器时通过命令行参数设置。有关更多信息,请参阅文档的此部分。
接下来是什么?
在本教程中,我们介绍了设置和查询 Triton 推理服务器的基础知识。这是一个涵盖将深度学习模型部署到生产环境所面临挑战的6部分教程系列的第1部分。第2部分涵盖并发模型执行和动态批处理。根据您的工作负载和经验,您可能想直接跳到第5部分,它涵盖构建包含多个模型、预处理和后处理步骤以及业务逻辑的集成流水线。
tangjicheng123/triton_Part_1-model_deployment
作者 tangjicheng123
创建时间: 2023-08-30 06:38:58+00:00
更新时间: 2023-08-30 06:42:19+00:00
在 Hugging Face 上查看