当今最受欢迎的型号之一是XgBoost。凭借解决分类和回归等各种问题的能力,XgBoost 已成为一种流行的选择,也属于基于树的模型类别。在这篇文章中,我们将深入了解
亚马逊 S
ageMaker如何
使用NVIDIA
Triton推理服务器为这些模型提供服务。 实时推理工作负载在延迟和吞吐量方面可能有不同的要求和服务级别协议 (SLA),可以使用 SageMaker 实时端点来满足。
SageMaker 提供
单一模型端点
,允许您针对逻辑端点部署单一机器学习 (ML) 模型。对于其他用例,您可以选择使用
多模型端点管理成本和性能 ,这允许您指定多个模型
以托管在逻辑端点后面。无论您选择哪个选项,SageMaker 端点都允许为要求最苛刻的企业客户提供可扩展机制,同时在众多功能中提供价值,包括
影子变体
、
自动扩展
以及与 Amazon CloudWatch 的原生集成 (有关更多信息,请参阅多模型端点部署的
C
l
oudWatch
指标)。
Triton 支持将各种后端作为引擎,以支持运行和提供各种 ML 模型以进行推理。对于任何 Triton 部署,了解后端行为如何影响您的工作负载以及预期结果至关重要,这样您才能取得成功。在这篇文章中,我们将帮助您了解
森林推理库 (FIL) 后端 ,该后端
由 SageMaker 上的 Triton 支持,以便您可以对工作负载做出明智的决定,并尽可能获得最佳性能和成本优化。
深入研究 FIL 后端
Triton 支持
FIL 后端
为树模型提供服务,例如
xgBoost、LightG
BM 、s
cikit-learn 随机森林 、R apids c
umL 随
机森林
以及 Treelite 支持的任何其他模型。
这些模型长期以来一直用于解决诸如分类或回归之类的问题。尽管这些类型的模型传统上在 CPU 上运行,但这些模型的普及和推理需求促成了各种提高推理性能的技术。FIL 后端通过使用 cUML 结构利用了其中的许多技术,并基于 C++ 和 CUDA 核心库构建,用于优化 GPU 加速器上的推理性能。
FIL 后端使用 cuML 的库来使用 CPU 或 GPU 内核来加速学习。 为了使用这些处理器,需要从主机内存(例如 NumPy 数组)或 GPU 数组(uDF、Numba、CuPy 或任何支持 __cuda_array_interface__)API 的库中引用数据。
将数据暂存到内存中后,FIL 后端可以在所有可用的 CPU 或 GPU 内核上运行处理。
FIL 后端线程可以在不使用主机的共享内存的情况下相互通信,但在集合工作负载中,应考虑主机内存。下图显示了一个集成调度器运行时架构,在该架构中,您可以微调内存区域,包括用于 Triton (C++) 和 Python 进程(Python 后端)之间用于与 FIL 后端交换张量(输入/输出)的 Python 进程(Python 后端)之间进程间通信的 CPU 可寻址共享内存。
Triton Inference Server 为开发人员提供了可配置的选项,以调整工作负载和优化模型性能。配置 d ynamic_batching
允许 Triton 保存客户端请求并在服务器端对其进行批处理,以便有效地使用 FIL 的并行计算来推断整个批次。 max_queue_delay_microsec
onds 选项可以安全地控制 Triton 等待形成批次的时间。
还有许多其他特定于 FIL 的
选项可用 ,这些选项
会影响性能和行为。我们建议从 storage
_type 开始。在 GPU 上运行后端时,FIL 会创建一个新的内存/数据结构,该结构表示 FIL 可能影响性能和占用空间的树。这可以通过环境参数 storage_ty
pe 进行配置 ,该参数具有密集、稀疏和自动选项。选择密集选项会消耗更多的 GPU 内存,并且并不总是能带来更好的性能,因此最好检查一下。相比之下,稀疏选项将消耗更少的 GPU 内存,并且性能可能与密集选项一样好或更好。选择 auto 会导致模型默认为密集,除非这样做会消耗的 GPU 内存明显多于稀疏内存。
在模型性能方面,你可以考虑强调 threads_per_tre
e 选项。在现实场景中,你可能会过度使用的一件事是, threads_per_tree
对吞吐量的影响比任何其他参数都大。将其设置为 1—32 之间的任意 2 次方是合法的。该参数的最佳值很难预测,但是当服务器需要处理更高的负载或处理更大的批量时,它往往会从比一次处理几行时更大的值中受益。
另一个需要注意的参数是 algo
,如果你在 GPU 上运行,它也可用。此参数确定用于处理推理请求的算法。 为此支持的选项有 ALGO_AUTO 、 NAIVE
、TREE_
REORG 和 BATCH_TREE_ RE ORG
。
这些选项决定了树中节点的组织方式,还可以提高性能。 对于稀疏存储, ALGO_AUTO
选项默认为 NAIVE,对于密集
存储,默认为 BATCH_TREE_REORG 。
最后,FIL 附带了 Shapley 解释器,可以使用 treeshap_output 参数将其激活。
但是,你应该记住,Shapley 输出由于其输出大小而损害了性能。
模型格式
目前没有用于存储基于森林的模型的标准文件格式;每个框架都倾向于定义自己的格式。为了支持多种输入文件格式,FIL 使用开源
Treelite
库导入数据。
这使得 FIL 能够支持在流行的框架(例如
xgBoost 和 LightGB
M)中训练的模型。
请注意,您提供的模型的格式必须在 c
onfig.pbtxt 文件中指定的 model_type
配置值中进行设置。
config.pbtxt
模型
存储库中的每个 模型
都 必须包含模型配置,该配置提供有关模型的必需和可选信息。
通常,此配置是在指定为 ModelConfig protobuf 的
config.pbtxt
文件中提供的。
要了解有关配置设置的更多信息,请参阅
模型配置
。以下是一些模型配置参数:
- max_batch_siz e — 这决定了可以传递给此模型的最大批量大小。通常,对传递到 FIL 后端的批处理大小的唯一限制是可用于处理批次的内存。对于 GPU 运行,可用内存由 Triton 的 CUDA 内存池的大小决定,启动服务器时可以通过命令行参数进行设置。
- 输入 — 本节中的选项告诉 Triton 每个输入样本的预期特征数量。
- 输出 — 本节中的选项告诉 Triton 每个样本将有多少输出值。如果
predict_proba
选项设置为 true,则将返回每个类的概率值。否则,将返回单个值,表示给定样本的预测类别。
- instance_ group — 它决定将创建该模型的实例数量以及它们将使用 GPU 还是 CPU。
- model_type
— 此字符串表示模型采用的格式(本示例中为 xgb oost_json,但是 xgboo
st、 lightg
bm
和 tl_checkpoint 也是有效的格式)。
- predict_proba — 如果设置为 true,则将返回每个类别的概率值,而不仅仅是类别预测 。
- output_class — 对于分类模型,此值设置为真,对于回归模型,设置为假。
- 阈值 -这是确定分类的分数阈值。当
output_class
设置 为 true 时,必须提供该值,但如果 p redict_proba
也设置为 true,则不会使用它。
- storage_type — 通常,在此设置中使用 AUTO 应该可以满足大多数用例。如果选择自动存储,FIL 将根据模型的大致大小使用稀疏或密集表示加载模型。在某些情况下,您可能需要将其明确设置为 SPARSE 以减少大型模型的内存占用。
SageMaker 上的 Triton 推理服务器
SageMaker
允许
您使用 NVIDIA Triton 推理服务器部署单模型和多模型端点。下图显示了 Triton 推理服务器的高级架构。
模型存储库
是基于文件系统的模型存储库,Triton 将提供这些模型用于推理。推理请求到达服务器并路由到相应的每个模型的调度器。Triton 实现了
多种调度和批处理算法
,可以逐个模型进行配置。每个模型的调度器可以选择执行推理请求的批处理,然后将请求传递到与模型类型 对应的
后端
。后端使用批处理请求中提供的输入进行推理,以生成请求的输出。然后返回输出。
在为 SageMaker 端点配置自动扩展组时,您可能需要将 SageMa kerVariantInvocationsPerInstan
ce 作为确定自动扩展组扩展特性的主要标准。此外,根据您的模型是在 GPU 还是 CPU 上运行,您也可以考虑使用 CPU 利用率或 GPU 利用率作为附加标准。请注意,对于单一模型端点,由于部署的模型完全相同,因此设置适当的策略以满足 SLA 非常简单。对于多模型端点,我们建议在给定端点后面部署类似的模型,以获得更稳定的可预测性能。在使用不同大小和要求的模型的用例中,您可能需要将这些工作负载分隔到多个多模型终端节点,或者花一些时间微调您的 Auto Scaling 组策略以获得最佳的成本和性能平衡。
有关 SageMaker 推理支持的 NVIDIA Triton 深度学习容器 (DLC) 列表,请参阅
可用的
深度学习容器映像。
SageMaker 笔记本电脑攻略
机器学习应用程序很复杂,通常需要数据预处理。在本笔记本中,我们将深入探讨如何在 SageMaker 多模型端点上使用 Triton 中的 FIL 后端部署基于树的机器学习模型,例如 XgBoost。我们还将介绍如何使用 Triton 中的集成功能为模型实现基于 Python 的数据预处理推理管道。这将允许我们从客户端发送原始数据,并在 Triton SageMaker 端点中同时进行数据预处理和模型推断,以实现最佳推理性能。
Triton 模型集合功能
Triton 推理服务器极大地简化了在生产环境中大规模部署 AI 模型。Triton Inference Server 附带一个便捷的解决方案,可简化预处理和后处理管道的构建。Triton Inference Server 平台提供了集成调度器,该调度器负责对参与推理过程的模型进行流水线,同时确保效率和优化吞吐量。使用集成模型可以避免传输中间张量的开销,并最大限度地减少必须发送给 Triton 的请求数量。
在本笔记本中,我们展示了如何使用集成功能通过 XgBoost 模型推断来构建数据预处理管道,您可以从中推断出来为流水线添加自定义后处理。
设置环境
我们首先设置所需的环境。我们安装了打包模型管道所需的依赖关系,并使用 Triton 推理服务器进行推断。我们还定义了
亚马逊云科技 身份和访问管理
(IAM) 角色,该角色将允许 SageMaker 访问模型构件和 NVIDIA Trit
on 亚马逊弹性容器注册表
(Amazon ECR) 映像。参见以下代码:
import boto3
import sagemaker
from sagemaker import get_execution_role
import pandas as pd
import numpy as np
import subprocess
sess = boto3.Session()
sm = sess.client("sagemaker")
##NOTE :Replace with your S3 bucket name
default_bucket=""
sagemaker_session = sagemaker.Session(default_bucket=default_bucket)
##NOTE : Make sure to have SageMakerFullAccess permission to the below IAM Role
role = get_execution_role()
client = boto3.client("sagemaker-runtime")
s3_bucket = sagemaker_session.default_bucket()
##NOTE : Latest SageMaker DLCs can be found here, please change region and account ids accordingly - https://github.com/aws/deep-learning-containers/blob/master/available_images.md
triton_image_uri = (
"{account_id}.dkr.ecr.{region}.{base}/sagemaker-tritonserver:23.02-py3".format(
account_id=account_id_map[region], region=region, base=base
))
为预处理依赖关系创建 Conda 环境
Triton 中的 Python 后端要求我们使用
Conda
环境来处理任何其他依赖关系。在这种情况下,我们使用 Python 后端对原始数据进行预处理,然后再将其输入到在 FIL 后端运行的 XgBoost 模型中。尽管我们最初使用 RAPIDS cuDF 和 cUML 来进行数据预处理,但这里我们在推理期间使用 Pandas 和 scikit-learn 作为预处理依赖关系。我们这样做有三个原因:
- 我们将介绍如何为你的依赖关系创建 Conda 环境,以及如何以 Triton 的 Python 后
端预期 的 格式
打包它。
- 通过显示在 CPU 上运行 Python 后端而 XGBoost 在 FIL 后端的 GPU 上运行的预处理模型,我们说明了 Triton 集成流水线中的每个模型如何在不同的框架后端以及不同的硬件配置上运行。
- 它重点介绍了 RAPIDS 库(cuDF、cumL)如何与 CPU 同类库(Pandas、scikit-learn)兼容。例如,我们可以展示如何在 cumL 中 创建的
标签编码器
在 scikit-learn 中使用,反之亦然。
我们按照
Triton 文档
中的说明打包预处理依赖关系(scikit-learn 和 Pandas),作为 Conda 环境 TAR 文件在 Python 后端使用。bash 脚本
create_prep_env.sh
创建了 Conda 环境 TAR 文件,然后我们将其移到预处理模型目录中。参见以下代码:
#!/bin/bash
conda create -y -n preprocessing_env python=3.8
source /opt/conda/etc/profile.d/conda.sh
conda activate preprocessing_env
export PYTHONNOUSERSITE=True
conda install -y -c conda-forge pandas scikit-learn
pip install conda-pack
conda-pack
在我们运行前面的脚本后,它会生成 preprocessing_env.tar.gz
,我们将其复制到预处理目录中:
!cp preprocessing_env.tar.gz model_cpu_repository/preprocessing/
!cp preprocessing_env.tar.gz model_gpu_repository/preprocessinggpu/
使用 Triton Python 后端设置预处理
为了进行预处理,我们使用 Triton 的
Python 后端
在推理进入服务器的原始数据请求时执行表格数据预处理(分类编码)。有关训练期间所做的预处理的更多信息,请参阅
训练笔记本
。
Python 后端支持在 Python 中实现预处理、后处理和任何其他自定义逻辑,并与 Triton 一起使用。在 SageMaker 上使用 Triton 需要我们首先设置一个包含我们要服务的模型的模型存储库文件夹。 我们已经在 cpu
_model_repository 和 gpu_model_repository 中建立了一个名为预处理的 Python 数据预处理模型。
Triton 对模型存储库布局有特定的要求。在顶级模型存储库目录中,每个模型都有自己的子目录,其中包含相应模型的信息。Triton 中的每个模型目录必须至少有一个代表模型版本的数字子目录。值 1 代表我们的 Python 预处理模型的版本 1。每个模型都由特定的后端运行,因此在每个版本的子目录中,必须有该后端所需的模型工件。在此示例中,我们使用 Python 后端,它要求将您提供的 Python 文件命名为 model.py,并且该文件需要实现
某些函数
。如果我们使用的是 PyTorch 后端,则需要一个 model.pt 文件,依此类推。有关模型文件命名规则的更多详细信息,请参阅
模型文件
。
我们在此处使用
的 model.py
Python 文件实现了所有表格数据预处理逻辑,将原始数据转换为可以输入到我们的 XgBoost 模型中的特征。
每个 Triton 模型还必须提供描述模型配置的 config.pbtxt
文件。要了解有关配置设置的更多信息,请参阅
模型配置
。我们的
config.pbtxt
文件将后端指定为 python,原始数据的所有输入列以及包含 15 个功能的预处理输出。我们还指定要在 CPU 上运行这个 Python 预处理模型。参见以下代码:
name: "preprocessing"
backend: "python"
max_batch_size: 882352
input [
{
name: "User"
data_type: TYPE_FP32
dims: [ 1 ]
},
{
name: "Card"
data_type: TYPE_FP32
dims: [ 1 ]
},
{
name: "Year"
data_type: TYPE_FP32
dims: [ 1 ]
},
{
name: "Month"
data_type: TYPE_FP32
dims: [ 1 ]
},
{
name: "Day"
data_type: TYPE_FP32
dims: [ 1 ]
},
{
name: "Time"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "Amount"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "Use Chip"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "Merchant Name"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "Merchant City"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "Merchant State"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "Zip"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "MCC"
data_type: TYPE_STRING
dims: [ 1 ]
},
{
name: "Errors?"
data_type: TYPE_STRING
dims: [ 1 ]
}
]
output [
{
name: "OUTPUT"
data_type: TYPE_FP32
dims: [ 15 ]
}
]
instance_group [
{
count: 1
kind: KIND_CPU
}
]
parameters: {
key: "EXECUTION_ENV_PATH",
value: {string_value: "$$TRITON_MODEL_DIRECTORY/preprocessing_env.tar.gz"}
}
为 FIL 后端设置基于树的 ML 模型
接下来,我们为基于树的 ML 模型(如 XgBoost)设置模型目录,该模型将使用 FIL 后端。
cpu_memory_repository 和 gpu_memory_
repository 的预期布局与我们之前展示
的布局类似。
这里, FIL
是模型的名称。 如果我们愿意,我们可以给它起一个不同的名字,比如 xgboost
。 1
是版本子目录,其中包含模型工件。在本例中,是我们保存的 xgboost.json 模型。
让我们创建这个预期的布局:
# move saved xgboost model into fil model directory
!mkdir -p model_cpu_repository/fil/1
!cp xgboost.json model_cpu_repository/fil/1/
!cp xgboost.json model_gpu_repository/filgpu/1/
我们需要配置文件 config.pbtxt
来 描述基于树的机器学习模型的模型配置,这样 Triton 中的 FIL 后端才能理解如何为其提供服务。有关更多信息,请参阅最新的通用
Triton 配置选项
和特定于
FIL 后端
的配置选项。在此示例中,我们仅重点介绍几个最常见和最相关的选项。
为 model_cpu_repository 创建 config.pbt
xt:
USE_GPU =False
FIL_MODEL_DIR = "./model_cpu_repository/fil"
# Maximum size in bytes for input and output arrays. If you are
# using Triton 21.11 or higher, all memory allocations will make
# use of Triton's memory pool, which has a default size of
# 67_108_864 bytes
MAX_MEMORY_BYTES = 60_000_000
NUM_FEATURES = 15
NUM_CLASSES = 2
bytes_per_sample = (NUM_FEATURES + NUM_CLASSES) * 4
max_batch_size = MAX_MEMORY_BYTES // bytes_per_sample
IS_CLASSIFIER = True
model_format = "xgboost_json"
# Select deployment hardware (GPU or CPU)
if USE_GPU:
instance_kind = "KIND_GPU"
else:
instance_kind = "KIND_CPU"
# whether the model is doing classification or regression
if IS_CLASSIFIER:
classifier_string = "true"
else:
classifier_string = "false"
# whether to predict probabilites or not
predict_proba = False
if predict_proba:
predict_proba_string = "true"
else:
predict_proba_string = "false"
config_text = f"""backend: "fil"
max_batch_size: {max_batch_size}
input [
{{
name: "input__0"
data_type: TYPE_FP32
dims: [ {NUM_FEATURES} ]
}}
]
output [
{{
name: "output__0"
data_type: TYPE_FP32
dims: [ 1 ]
}}
]
instance_group [{{ kind: {instance_kind} }}]
parameters [
{{
key: "model_type"
value: {{ string_value: "{model_format}" }}
}},
{{
key: "predict_proba"
value: {{ string_value: "{predict_proba_string}" }}
}},
{{
key: "output_class"
value: {{ string_value: "{classifier_string}" }}
}},
{{
key: "threshold"
value: {{ string_value: "0.5" }}
}},
{{
key: "storage_type"
value: {{ string_value: "AUTO" }}
}}
]
dynamic_batching {{}}"""
config_path = os.path.join(FIL_MODEL_DIR, "config.pbtxt")
with open(config_path, "w") as file_:
file_.write(config_text)
同样,为 m odel_gpu_repository 设置 config.pbtxt
(注意区别在 于 USE_GPU =
True):
USE_GPU = True
FIL_MODEL_DIR = "./model_gpu_repository/filgpu"
# Maximum size in bytes for input and output arrays. If you are
# using Triton 21.11 or higher, all memory allocations will make
# use of Triton's memory pool, which has a default size of
# 67_108_864 bytes
MAX_MEMORY_BYTES = 60_000_000
NUM_FEATURES = 15
NUM_CLASSES = 2
bytes_per_sample = (NUM_FEATURES + NUM_CLASSES) * 4
max_batch_size = MAX_MEMORY_BYTES // bytes_per_sample
IS_CLASSIFIER = True
model_format = "xgboost_json"
# Select deployment hardware (GPU or CPU)
if USE_GPU:
instance_kind = "KIND_GPU"
else:
instance_kind = "KIND_CPU"
# whether the model is doing classification or regression
if IS_CLASSIFIER:
classifier_string = "true"
else:
classifier_string = "false"
# whether to predict probabilites or not
predict_proba = False
if predict_proba:
predict_proba_string = "true"
else:
predict_proba_string = "false"
config_text = f"""backend: "fil"
max_batch_size: {max_batch_size}
input [
{{
name: "input__0"
data_type: TYPE_FP32
dims: [ {NUM_FEATURES} ]
}}
]
output [
{{
name: "output__0"
data_type: TYPE_FP32
dims: [ 1 ]
}}
]
instance_group [{{ kind: {instance_kind} }}]
parameters [
{{
key: "model_type"
value: {{ string_value: "{model_format}" }}
}},
{{
key: "predict_proba"
value: {{ string_value: "{predict_proba_string}" }}
}},
{{
key: "output_class"
value: {{ string_value: "{classifier_string}" }}
}},
{{
key: "threshold"
value: {{ string_value: "0.5" }}
}},
{{
key: "storage_type"
value: {{ string_value: "AUTO" }}
}}
]
dynamic_batching {{}}"""
config_path = os.path.join(FIL_MODEL_DIR, "config.pbtxt")
with open(config_path, "w") as file_:
file_.write(config_text)
使用集合设置数据预处理 Python 后端和 FIL 后端的推理管道
现在,我们已经准备好使用集成模型为数据预处理和基于树的模型推断设置推理管道。
集合模型代表一个或多个模型的流水线,以及这些模型之间输入和输出张量的连接。在这里,我们使用集成模型在 Python 后端构建数据预处理管道,然后在 FIL 后端建立 XgBoost。
集 合
模型目录的预期布局与我们之前展示的布局类似:
# create model version directory for ensemble CPU model
!mkdir -p model_cpu_repository/ensemble/1
# create model version directory for ensemble GPU model
!mkdir -p model_gpu_repository/ensemble/1
我们 按照集成模型中的指导创建了集成模型的
config.pbtxt
。
重要的是,我们需要在 config.pbtxt
中设置集合调度器 ,它指定集合内模型之间的数据流。集合调度器收集每个步骤中的输出张量,并根据规范将其作为输入张量提供给其他步骤。
打包模型存储库并上传到 Amazon S3
最后,我们得到了以下模型存储库目录结构,其中包含 Python 预处理模型及其依赖关系以及 XgBoost FIL 模型和模型集合。
我们将目录及其内容打包为 model.tar.gz
,然后上传到
亚马逊 Simple Storage Servic
e (Amazon S3)。在此示例中,我们有两个选项:使用基于 CPU 的实例或基于 GPU 的实例。当您需要更高的处理能力并想要使用 CUDA 内核时,基于 GPU 的实例更合适。
使用以下代码为基于 CPU 的实例(针对 CPU 进行了优化)创建和上传模型包:
!tar —exclude='.ipynb_checkpoints' -czvf model-cpu.tar.gz -C model_cpu_repository .
model_uri_cpu = sagemaker_session.upload_data(
path="model-cpu.tar.gz", key_prefix="triton-fil-mme-ensemble"
)
使用以下代码为基于 GPU 的实例(针对 GPU 进行了优化)创建和上传模型包:
!tar —exclude='.ipynb_checkpoints' -czvf model-gpu.tar.gz -C model_gpu_repository .
model_uri_cpu = sagemaker_session.upload_data(
path="model-gpu.tar.gz", key_prefix="triton-fil-mme-ensemble"
)
创建 SageMaker 端点
现在,我们将模型工件存储在 S3 存储桶中。在此步骤中,我们还可以提供额外的环境变量 SAGEMAKER_TRITON_DEFAULT_MODEL_NAME,它指定 Triton 要加载的模型的名称
。此密钥的值应与上传到 Amazon S3 的模型包中的文件夹名称相匹配。对于单一模型,此变量是可选的。就集成模型而言,必须指定此密钥才能在 SageMaker 中启动 Triton。
此外,你可以设置 SAGEMAKER_TRITON_BUFFER_MANAGER_THREAD_COUNT 和 SAGEMAKER_TRITON_TRITON_THREAD_
COUNT 来优化线程数。
# Set the primary path for where all the models are stored on S3 bucket
model_location = f"s3://{s3_bucket}/triton-fil-mme-ensemble/"
sm_model_name = f"{user_profile}" + time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
container = {
"Image": triton_image_uri,
"ModelDataUrl": model_location,
"Mode": "MultiModel",
"Environment": {
"SAGEMAKER_TRITON_DEFAULT_MODEL_NAME": "ensemble",
# "SAGEMAKER_TRITON_DEFAULT_MODEL_NAME": model_uri.rsplit('/')[-2], #m_name,
# "SAGEMAKER_TRITON_LOG_VERBOSE": "true", #"200",
# "SAGEMAKER_TRITON_SHM_DEFAULT_BYTE_SIZE" : "20000000", #"1677721600", #"16777216000", "16777216"
# "SAGEMAKER_TRITON_SHM_GROWTH_BYTE_SIZE": "1048576"
},
}
create_model_response = sm.create_model(
ModelName=sm_model_name, ExecutionRoleArn=role, PrimaryContainer=container
)
我们使用前面的模型来创建端点配置,在其中我们可以指定我们想要在端点中使用的实例类型和数量。
eendpoint_config_name = f"{user_profile}" + time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
create_endpoint_config_response = sm.create_endpoint_config(
EndpointConfigName=endpoint_config_name,
ProductionVariants=[
{
"InstanceType": "ml.g4dn.xlarge",
"InitialVariantWeight": 1,
"InitialInstanceCount": 1,
"ModelName": sm_model_name,
"VariantName": "AllTraffic",
}
],
)
我们使用此端点配置来创建 SageMaker 端点并等待部署完成。使用 SageMaker MME,我们可以通过重复此过程来选择托管多个集成模型,但对于此示例,我们坚持使用一个部署:
endpoint_name = f"{studio_user_profile_output}-lab1-" + time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
create_endpoint_response = sm.create_endpoint(
EndpointName=endpoint_name, EndpointConfigName=endpoint_config_name
)
成功部署 后,状态将更改为 InServic
e。
调用 SageMaker 端点上托管的模型
端点运行后,我们可以使用一些示例原始数据,使用 JSON 作为负载格式进行推断。
对于推理请求格式,Triton 使用
KfServing 社区标准推理协议
。
参见以下代码:
data_infer = pd.read_csv("data_infer.csv")
STR_COLUMNS = [
"Time",
"Amount",
"Zip",
"MCC",
"Merchant Name",
"Use Chip",
"Merchant City",
"Merchant State",
"Errors?",
]
batch_size = len(data_infer)
payload = {}
payload["inputs"] = []
data_dict = {}
for col_name in data_infer.columns:
data_dict[col_name] = {}
data_dict[col_name]["name"] = col_name
if col_name in STR_COLUMNS:
data_dict[col_name]["data"] = data_infer[col_name].astype(str).tolist()
data_dict[col_name]["datatype"] = "BYTES"
else:
data_dict[col_name]["data"] = data_infer[col_name].astype("float32").tolist()
data_dict[col_name]["datatype"] = "FP32"
data_dict[col_name]["shape"] = [batch_size, 1]
payload["inputs"].append(data_dict[col_name])
#Invoke the endpoint
# Change the TargetModel to either CPU or GPU
response = client.invoke_endpoint(
EndpointName=endpoint_name, ContentType="application/octet-stream", Body=json.dumps(payload),TargetModel="model-cpu.tar.gz",
)
#Read the results
response_body = json.loads(response["Body"].read().decode("utf8"))
predictions = response_body["outputs"][0]["data"]
CLASS_LABELS = ["NOT FRAUD", "FRAUD"]
predictions = [CLASS_LABELS[int(idx)] for idx in predictions]
print(predictions)
博客中提到的笔记本可以在
GitHub 存储库
中找到 。
最佳实践
除了我们前面提到的微调 FIL 后端设置的选项外,数据科学家还可以确保对后端的输入数据进行优化,以供引擎处理。尽可能将行优先格式的数据输入到 GPU 数组中。其他格式将需要内部转换并占用周期,从而降低性能。
由于 FIL 数据结构在 GPU 内存中维护的方式,请注意树的深度。树深度越深,您的 GPU 内存占用量就越大。
使用 instance_group_count
参数添加工作进程并提高 FIL 后端的吞吐量,这将导致 CPU 和 GPU 内存消耗量增加。此外,请考虑可用于提高吞吐量的 Sagemaker 特定变量,例如 HTTP 线程、HTTP 缓冲区大小、批量大小和最大延迟。
结论
在这篇文章中,我们将深入探讨Triton Inference Server在SageMaker上支持的 FIL 后端。此后端为基于树的模型(例如流行的 XgBoost 算法)提供 CPU 和 GPU 加速。要获得最佳的推理性能,有许多选项可供考虑,例如批量大小、数据输入格式和其他可以调整以满足需求的因素。SageMaker 允许您将此功能与单模型和多模型端点结合使用,以平衡性能和成本节约。
我们鼓励您参考这篇文章中的信息,看看SageMaker能否满足您的托管需求,提供基于树的模型,满足您对降低成本和提高工作负载性能的要求。
这篇文章中引用的笔记本可以在 SageMaker 示例
GitHub
存储库中找到。 此外,你可以在
GitHub
上找到 FIL 后端的最新文档 。
作者简介
Raghu Ramesha 是亚马逊 SageMaker 服务团队的高级机器学习解决方案架构师。他专注于帮助客户构建、部署机器学习生产工作负载并将其大规模迁移到 SageMaker。他专攻机器学习、人工智能和计算机视觉领域,并拥有德克萨斯大学达拉斯分校的计算机科学硕士学位。在业余时间,他喜欢旅行和摄影。
詹姆斯·帕克 是亚马逊网络服务的解决方案架构师。他与 Amazon.com 合作,在 亚马逊云科技 上设计、构建和部署技术解决方案,并对人工智能和机器学习特别感兴趣。在业余时间,他喜欢寻找新的文化、新的体验,并及时了解最新的技术趋势。
达瓦尔·帕特尔 是 亚马逊云科技 的首席机器学习架构师。他曾与从大型企业到中型初创企业等组织合作,研究与分布式计算和人工智能有关的问题。他专注于深度学习,包括自然语言处理和计算机视觉领域。他帮助客户在亚马逊 SageMaker 上实现高性能模型推断。
刘佳虹 是 NVIDIA 云服务提供商团队的解决方案架构师。他帮助客户采用机器学习和人工智能解决方案,这些解决方案利用 NVIDIA 加速计算来应对他们的训练和推理挑战。闲暇时,他喜欢折纸、DIY 项目和打篮球。
Kshitiz Gupta 是 NVIDIA 的解决方案架构师。他喜欢向云客户介绍 NVIDIA 提供的 GPU AI 技术,并帮助他们加速机器学习和深度学习应用程序。工作之余,他喜欢跑步、远足和观赏野生动物。