| name: "direct_stateful_model"platform: "tensorrt_plan"max_batch_size: 2sequence_batching { max_sequence_idle_microseconds: 5000000 direct { } control_input [ { name: "START" control [ { kind: CONTROL_SEQUENCE_START fp32_false_true: [ 0, 1 ] } ] }, { name: "READY" control [ { kind: CONTROL_SEQUENCE_READY fp32_false_true: [ 0, 1 ] } ] } ]} # 续接右栏 | # 上接左栏input [ { name: "INPUT" data_type: TYPE_FP32 dims: [ 100, 100 ] }]output [ { name: "OUTPUT" data_type: TYPE_FP32 dims: [ 10 ] }]instance_group [ { count: 2 }] |
每个模型实例都在维护每个批处理槽的状态,并期望将给定序列的所有推理请求分发到同一槽,以便正确更新状态。对于本例,这意味着 Triton 可以同时 4 个序列进行推理。
使用直接调度策略,序列批处理程序会执行以下动作:
| 所识别的推理请求种类 | 执行动作 |
| 需要启动新序列 | 1. 有可用处理槽时:就为该序列分配批处理槽2. 无可用处理槽时:就将推理请求放在积压工作中 |
| 是已分配处理槽序列的一部分 | 将该请求分发到该配置好的批量处理槽 |
| 是积压工作中序列的一部分 | 将请求放入积压工作中 |
| 是最后一个推理请求 | 1. 有积压工作时:将处理槽分配给积压工作的序列2. 有积压工作:释放该序列处理槽给其他序列使用 |
图左显示了到达 Triton 的 5 个请求序列,每个序列可以由任意数量的推理请求组成。图右侧显示了推理请求序列是如何随时间安排到模型实例上的,
随着时间的推移(从右向左),会发生以下情况:| 直接(direct)策略 | 最旧的(oldest)策略 |
|
direct {} |
oldest { max_candidate_sequences: 4 } |
使用最旧的调度策略,序列批处理程序会执行以下工作:
| 所识别的推理请求种类 | 执行动作 |
| 需要启动新序列 | 尝试查找具有候选序列空间的模型实例,如果没有实例可以容纳新的候选序列,就将请求放在一个积压工作中 |
| 已经是候选序列的一部分 | 将该请求分发到该模型实例 |
| 是积压工作中序列的一部分 | 将请求放入积压工作中 |
| 是最后一个推理请求 | 模型实例立即从积压工作中删除一个序列,并将其作为模型实例中的候选序列,或者记录如果没有积压工作,模型实例可以处理未来的序列。 |
这里假设每个请求的长度是相同的,那么左边候选序列中送进右边批量处理槽的顺序,就是上图中间的排列顺序。
最旧的策略从最旧的请求中形成一个动态批处理,但在一个批处理中从不包含来自给定序列的多个请求,例如上面序列 D 中的最后两个推理不是一起批处理的。
以上是关于有状态模型的“调度策略”主要内容,剩下的“集成模型”部分,会在下篇文章中提供完整的说明。
原文标题:NVIDIA Triton 系列文章(11):模型类别与调度器-2
文章出处:【微信公众号:NVIDIA英伟达企业解决方案】欢迎添加关注!文章转载请注明出处。
全部0条评论
快来发表一下你的评论吧 !