Triton 响应缓存#
概述#
在本文档中,*推理请求*是指模型名称、模型版本和输入张量(名称、形状、数据类型和张量数据),它们构成提交给 Triton 的请求。推理结果是指由推理执行产生的输出张量(名称、形状、数据类型和张量数据)。响应缓存由 Triton 用于保存为先前执行的推理请求生成的推理结果。Triton 将维护响应缓存,以便命中缓存的推理请求无需执行模型来生成结果,而是从缓存中提取其结果。对于某些用例,这可以显着减少推理请求延迟。
Triton 使用推理请求的哈希访问响应缓存,该哈希包括模型名称、模型版本和模型输入。如果在缓存中找到哈希,则从缓存中提取相应的推理结果并将其用于请求。发生这种情况时,Triton 无需执行模型来生成推理结果。如果在缓存中未找到哈希,则 Triton 执行模型以生成推理结果,然后将该结果记录在缓存中,以便后续的推理请求可以(重新)使用这些结果。
用法#
为了在给定模型上使用缓存,必须在服务器端和模型的模型配置中启用它。有关更多详细信息,请参见以下各节。
在服务器端启用缓存#
响应缓存通过在启动 Triton 服务器时指定缓存实现名称 <cache>
和相应的配置在服务器端启用。
通过 CLI,这转化为设置 tritonserver --cache-config <cache>,<key>=<value> ...
。例如
tritonserver --cache-config local,size=1048576
[!NOTE] 如果使用非交互式 shell,您可能需要指定不带空格的参数,如下所示:
--cache-config=<cache>,<key>=<value>
。
对于进程内 C API 应用程序,这转化为调用 TRITONSERVER_SetCacheConfig(const char* cache_implementation, const char* config_json)
。
这允许用户在服务器启动时全局启用/禁用缓存。
为模型启用缓存#
默认情况下,即使使用 --cache-config
标志全局启用了响应缓存,也没有模型使用响应缓存。
对于要使用响应缓存的给定模型,该模型还必须在其模型配置中启用响应缓存
# config.pbtxt
response_cache {
enable: true
}
这允许用户为特定模型启用/禁用缓存。
有关为每个模型启用响应缓存的更多信息,请参见模型配置文档。
缓存实现#
从 23.03 版本开始,Triton 拥有一组 TRITONCACHE API,用于与用户选择的缓存实现进行通信。
缓存实现是一个共享库,它实现了所需的 TRITONCACHE API,并在服务器启动时动态加载(如果已启用)。
Triton 最新的 tritonserver 发布容器 附带以下开箱即用的缓存实现
local:
/opt/tritonserver/caches/local/libtritoncache_local.so
redis:
/opt/tritonserver/caches/redis/libtritoncache_redis.so
借助这些 TRITONCACHE API,tritonserver
公开了一个新的 --cache-config
CLI 标志,使用户可以灵活地自定义要使用的缓存实现以及如何配置它。与 --backend-config
标志类似,预期格式为 --cache-config <cache_name>,<key>=<value>
,并且可以多次指定以指定多个键(如果缓存实现需要)。
本地缓存#
local
缓存实现等效于 23.03 版本之前内部使用的响应缓存。有关更多特定于实现的详细信息,请参见本地缓存实现。
当使用非零 SIZE
指定 --cache-config local,size=SIZE
时,Triton 会在 CPU 内存中分配请求的大小,并且 在所有推理请求和所有模型之间共享缓存。
Redis 缓存#
redis
缓存实现公开了 Triton 与 Redis 服务器通信以进行缓存的能力。redis_cache
实现本质上是一个 Redis 客户端,充当 Triton 和 Redis 之间的中介。
列出在 Triton 上下文中 redis
缓存相比于 local
缓存的一些优势
Redis 服务器可以远程托管,只要 Triton 可以访问它,因此它不直接绑定到 Triton 进程生命周期。
这意味着 Triton 可以重新启动,并且仍然可以访问以前缓存的条目。
这也意味着 Triton 不必与缓存竞争内存/资源使用。
多个 Triton 实例可以通过配置每个 Triton 实例以与同一 Redis 服务器通信来共享缓存。
Redis 服务器可以独立于 Triton 进行更新/重启,并且在任何 Redis 服务器停机期间,Triton 将回退到像没有缓存访问一样运行,并记录相应的错误。
一般来说,可以根据您的用例需要配置/部署 Redis 服务器,而 Triton 的 redis
缓存将仅充当您的 Redis 部署的客户端。有关配置 Redis 服务器的问题和详细信息,应查阅 Redis 文档。
有关 Triton 特定的 redis
缓存实现详细信息/配置,请参见redis 缓存实现。
自定义缓存#
借助 TRITONCACHE API 接口,用户现在可以实现自己的缓存以满足任何特定用例的需求。要查看缓存开发人员必须实现的所需接口,请参见 TRITONCACHE API 标头。local
或 redis
缓存实现可以用作参考。
成功开发和构建自定义缓存后,生成的共享库(例如:libtritoncache_<name>.so
)必须放置在缓存目录中,类似于 local
和 redis
缓存实现所在的目录。默认情况下,此目录是 /opt/tritonserver/caches
,但可以根据需要使用 --cache-dir
指定自定义目录。
为了将此示例放在一起,如果自定义缓存被命名为“custom”(此名称是任意的),则默认情况下,Triton 会期望在 /opt/tritonserver/caches/custom/libtritoncache_custom.so
找到缓存实现。
弃用说明#
注意 在 23.03 之前,启用
local
缓存过去是通过在使用--response-cache-byte-size
标志启动 Triton 时设置非零大小(以字节为单位)来完成的。从 23.03 开始,
--response-cache-byte-size
标志现在已弃用,应改用--cache-config
。为了向后兼容,--response-cache-byte-size
将通过转换为相应的--cache-config
参数在后台继续运行,但它将默认为使用local
缓存实现。使用--response-cache-byte-size
标志无法选择其他缓存实现。例如,
--response-cache-byte-size 1048576
将等效于--cache-config local,size=1048576
。但是,--cache-config
标志更加灵活,应改用它。
警告
由于内部内存管理要求,对于
--cache-config local,size=<small_value>
或--response-cache-byte-size
的非常小的值(例如:小于 1024 字节),local
缓存实现可能无法初始化。如果遇到相对较小的缓存大小的初始化错误,请尝试增加它。同样,大小受系统上可用 RAM 的上限限制。如果遇到非常大的缓存大小设置的初始分配错误,请尝试减小它。
性能#
响应缓存旨在用于预期会产生大量重复请求(缓存命中)的用例,因此将受益于缓存。“significant”(显着)一词在这里是主观的,取决于用例,但一个简单的解释是考虑预期缓存命中/未命中的比例,以及计算响应所花费的平均时间。
对于缓存命中很常见且计算成本很高的情况,缓存可以显着提高整体性能。
对于大多数请求是唯一的(缓存未命中)或计算速度快/成本低(模型不是计算密集型)的情况,由于管理缓存和与缓存通信的开销,缓存可能会对整体性能产生负面影响。
集成模型缓存#
如果集成中的所有组成模型也支持缓存,则对集成模型的顶层请求支持缓存。
同样,如果集成中的组成模型不支持缓存,则集成模型将继承此限制,也不支持缓存。有关哪些类型的模型支持缓存,请参见下面的已知限制。
集成上的缓存命中将完全跳过向组成模型发送请求,并从集成模型返回缓存的响应。
集成上的缓存未命中将回退到标准推理,并且请求将像往常一样继续传递到组成模型。
集成及其组成模型可以独立启用缓存,并且每个模型在启用时都维护自己的缓存。请求可能在集成级别上是缓存未命中,但随后集成内的中间模型可能会发生缓存命中,具体取决于正在组成的模型的输入和输出。组成模型不需要启用缓存即可在集成级别启用它。
已知限制#
只有位于 CPU 内存中的输入张量才能进行哈希处理以访问缓存。如果推理请求包含不在 CPU 内存中的输入张量,则不会对该请求进行哈希处理,因此不会缓存响应。
只有所有输出张量都位于 CPU 内存中的响应才有资格进行缓存。如果响应中的任何输出张量未位于 CPU 内存中,则不会缓存该响应。
缓存仅使用推理请求哈希进行访问。因此,如果两个不同的推理请求生成相同的哈希(哈希冲突),则 Triton 可能会错误地将缓存的结果用于推理请求。哈希是一个 64 位的值,因此冲突的可能性很小。
只有成功的推理请求才会缓存其响应。如果请求失败或在推理期间返回错误,则不会缓存其响应。
只有通过默认调度器或动态批处理调度器的请求才有资格进行缓存。序列批处理器目前不支持响应缓存。
响应缓存目前不支持解耦模型。