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 标头localredis 缓存实现可以用作参考。

成功开发和构建自定义缓存后,生成的共享库(例如:libtritoncache_<name>.so)必须放置在缓存目录中,类似于 localredis 缓存实现所在的目录。默认情况下,此目录是 /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 位的值,因此冲突的可能性很小。

  • 只有成功的推理请求才会缓存其响应。如果请求失败或在推理期间返回错误,则不会缓存其响应。

  • 只有通过默认调度器或动态批处理调度器的请求才有资格进行缓存。序列批处理器目前不支持响应缓存。

  • 响应缓存目前不支持解耦模型