我不会用 Triton 系列:Rate Limiter 的使用
Rate Limiter
这篇文章记录 Rate Limter 的使用方法,主要来自于文档。
从效果上来说,Rate Limiter 的作用是限制了请求分发到模型实例上。从实现上来说,Rate Limiter 引入了 “Resource” 的概念,表示一个模型实例需要的资源,当系统中存在足够的资源,这个模型就会执行。如果资源不够,那么一个请求需要等待其他模型实例释放资源。最终的表现就是好像限制了速度一样。
链接:https://github.com/triton-inference-server/server/blob/main/docs/rate_limiter.md
上手使用
概念
Resources
表示一个模型实例执行请求的时候需要的资源,资源分为两种类型,全局的 (global) 和某个设备上的 (per-device)。系统中有的资源数量有两种计算方式:
- 第一种,由所有的模型实例上指定的最大数量。
- 第二种,启动的时候设置。
Priority:
表示执行的优先级。从文档的表述中,我们可以知道,数字越小优先级越高,而且还是以概率的方式进行调度的,而不是谁优先谁执行。
An instance with priority 2 will be given 1/2 the number of scheduling chances as an instance with priority 1.
例子
我们先描述一下设想的例子。我们有四个模型,一个模型 A 不管怎样都不会执行,一个模型 B 不管怎样都会执行,两个模型 CD 需要争夺资源。每个模型都是 python backend 的 add_sub 模型,我们在 execute 方法中加入一个睡眠时间 10 秒钟。启动的时候指定资源的数量。
A: [R1: 10, R2: 5, R3: 10]
B: [R3: 3]
C: [R1: 5, R2: 5]
D: [R1: 4, R2: 6]
为了实验,将 R3 设置为 global 类型。其实如果是在单卡情况下或者 CPU,global 和某设备的资源就没有区别了。因为我们使用的还是 Python backend,所以只能使用 CPU 了。
按照官方的文档,我们模仿写出 A 的配置,BCD 的配置是类似的,这里就不重复了。为了一些实验,每个模型设置两个模型实例。
instance_group [
{
count: 2
kind: KIND_CPU
rate_limiter {
resources [
{
name: "R1"
count: 10
},
{
name: "R2"
count: 5
},
{
name: "R3"
global: True
count: 10
}
]
priority: 1
}
}
]
启动
完整的代码在这里:https://github.com/zzk0/triton/tree/master/rate
配置好之后,启动的时候需要带上选项 --rate-limit。如果不带上这个选项的话,它是不会启用 rate limiter 的。
下面是命令行输出的,和 rate limiter 相关的部分。
--rate-limit <string>
Specify the mode for rate limiting. Options are
"execution_count" and "off". The default is "off". For "execution_count", the
server will determine the instance using configured priority and the
number of time the instance has been used to run inference. The
inference will finally be executed once the required resources are
available. For "off", the server will ignore any rate limiter config and
run inference as soon as an instance is ready.
--rate-limit-resource <<string>:<integer>:<integer>>
The number of resources available to the server. The format
of this flag is
--rate-limit-resource=<resource_name>:<count>:<device>. The <device> is optional and if not listed will be applied to
every device. If the resource is specified as "GLOBAL" in the model
configuration the resource is considered shared among all the devices
in the system. The <device> property is ignored for such resources.
This flag can be specified multiple times to specify each resources
and their availability. By default, the max across all instances
that list the resource is selected as its availability. The values for
这个是英伟达文档中给出的例子。R1 和 R3 的设置是有区别的,在模型配置文件中,R1 不是全局的,所以按照上面命令行的帮助信息说的,R1 会在每个设备上都有,R3 则是一个全局资源。
--rate-limit-resource=R1:10 --rate-limit-resource=R2:5:0 --rate-limit-resource=R2:8:1 --rate-limit-resource=R3:2
GLOBAL: [R3: 2]
device0: [R1: 10, R2: 5]
device1: [R1: 10, R2: 8]
启动的时候,我们带上以下参数,保证了 A 一定不会执行,B 一定会执行,CD 争夺资源执行。在进入 docker 之前,需要设置好目录映射,将我的那个仓库映射到 /triton 这个文件夹下面。
./bin/tritonserver --model-store=/triton/triton/rate/ --rate-limit=execution_count --rate-limit-resource=R1:8 --rate-limit-resource=R2:7 --rate-limit-resource=R3:10
启动的时候会发现以下信息,表示启动失败了啊... 所以咱们把 A 删掉吧。
Resource count for "R1" is limited to 8 which will prevent scheduling of one or more model instances, the minimum required count is 10
之后使用客户端脚本进行请求就好了,如果没有资源,那么就要进行等待。为了试验优先级,我们可以将模型 D 的 priority 设置为 10,然后 C 设置为 1。请求的时候,交互使用两个客户端去做请求,之后会发现 C 执行完了之后,才轮到 D 执行。
问题
问:如果指定了 count 为 2,可是每个设备上的资源数量是限定了的,那么指定了 2 是否就意味着每次只能有一个模型执行呢?
答:是的,只能有一个实例在执行。这是实验结果表明的,开两个模型实例,execute 的时候 sleep 10s。第一个脚本执行 10s,第二脚本执行 18s(2s 切换 console, 输入命令)。这说明了,有两个模型实例,没有满足需要的资源,它就是不执行。
问:资源是设备上的,那么如果我不用 GPU 呢?
答:我们是不是可以将 CPU 也看成一个和 GPU 一样的设备呢?将 CPU 视为一个设备就好了。