tritonserver的metrics参数说明

tritonserver框架部署指标评估工具metrics(二)

一、简介

之前详细了解过model-analyser工具,可以用于单个模型(或者多个模型测试,但是对于需要级联多个模型的情况,无法联调实现最佳的综合性能)。这里简单介绍一下另一个评估工具,是tritonserver 自带的小工具。相比如model-analyser,tritonsever自带的metrics性能评估指标,更加适合以下场景:

  1. 需要分析在多个模型存在级联关系的情况下,辅助开发人员寻找最佳的模型实例配置信息。
  2. 对于BLS模型来说,因为很多图像的前后处理都是在cpu端完成的,很可能整个请求的时间瓶颈都集中在cpu上计算的前后处理代码,以及GPU模型和CPU前后处理时间不匹配导致的排队时延上。metrics工具可以分析在每个模块上的计算时间和排队时间。开发人员可以根据统计的每个模块的排队时间来配置不同模块的instance数量,达到性能的最佳配置。

二、启动tritonserver的说明

默认已经成功安装了tritonserver的docker容器,挂载了响应的模型代码并启动了如下的tritonserver脚本:

 PYTHONIOENCODING=utf-8 CUDA_VISIBLE_DEVICES=3 tritonserver --model-repository=text_server_normal

此处的模型仓库是采用BLS编写的模型。
启动客户端访问代码,我采用的是locust进行多用户的并发访问。
在并发测试完成之后,通过访问下面的地址进行查看性能指标

curl localhost:8002/metrics

如果上述指令无法工作,则需要明显的添加–allow-metrics=true进行tritonserver的启动。

三、主要的指标

1. 推理请求指标

1.1 数量挂的

  1. 请求数量nv_inference_request_success/failure:表示客户端发来的请求request的数量,如果客户端发来两个请求,其中一个batch为1,另一个batch为8,请求数量为2
  2. 推理数量nv_inference_count:模型实际会处理的样例的数量,上面的例子中为9
  3. 执行数量nv_inference_exec_count:模型实际执行前向处理的数量,上面例子中为2

1.2 时间挂的:

  1. 请求时间nv_inference_request_duration_us:端到端处理一个请求的时间(包括缓存的请求)
  2. 队列时间nv_inference_queue_duration_us:计算每个模型在执行之前,在schedule队列中的等待时间
  3. 输入处理时间nv_inference_compute_input_duration_us
  4. 执行时间nv_inference_compute_infer_duration_us
  5. 输出处理时间 nv_inference_compute_output_duration_us

1.3 GPU相关的指标

包括GPU功率、GPU的利用率,GPU显存占用情况;通过设置参数 --allow-gpu-metrics True来设置

1.4. CPU相关的指标

CPU的利用率,CPU的总内存和使用内存情况。
通过参数–allow-cpu-metrics true来配置,目前这个参数只能在linux环境中设置,原理是收集/proc_filesystem中的内存信息和状态信息来实现的,比如/proc/stat and /proc/meminfo

1.5 响应缓存指标Response Cache Metrics

response cache的概念
一个推理请求可以由模型名称、模型版本和输入tensor唯一确定。response cache用于缓存历史的推理结果。如果新的请求在缓存中可以找到,那么久直接输出缓存结果,不会进行模型推理的步骤。缓存可以看成一个map,key为推理请求的模型名称、模型版本和输入tensor构成的hash值
可以通过–response-cache-byte-size这个参数设置,这个参数默认为0,也就是不会开启缓存。当设置这个参数小于1024时,效果也不好。如果需要设置这个参数,那么值大一点,但是不要超过RAM,否则也会报错。
在显示指标的时候,也会有这一类的指标。
显然当开启response cache的时候,请求的耗时会受到缓存影响(好的影响是hit的请求多了,Cache Hit Lookup Time就可以替代"Compute Input Time" / “Compute Time” / "Compute Output Time"时间;不好的影响是查询缓存造成的耗时以及插入新的请求造成的插入缓存)。

1.5.1 缓存区域的利用率nv_cache_util
1.5.2 数量挂的

  • 缓存区保存的response数量(all model) nv_cache_num_entries
  • 缓存搜寻的次数(all model) nv_cache_num_lookups
  • 缓存击中次数(all model) nv_cache_num_hits
  • 缓存未击中次数(all model) nv_cache_num_misses
  • 缓存删除次数(all model) nv_cache_num_evictions
  • 缓存击中次数(per model) nv_cache_num_hits_per_model
  • 缓存未击中次数(per model) nv_cache_num_misses_per_model

1.5.3 时间挂的

  • 缓存搜索时间:nv_cache_lookup_duration访问请求用与在缓存中查找缓存响应的累积时间,统计所有模型的累积时间
  • 缓存插入时间:nv_cache_insertion_duration访问请求用于在缓存中插入response的累积时间,统计所有模型的累积时间
  • 缓存击中搜索时间:nv_cache_hit_lookup_duration_per_model访问请求用于在缓存中搜寻到指定的响应的查找时间,单个模型统计
  • 缓存未击中搜索时间:nv_cache_miss_lookup_duration_per_model ,不解释类似上面
  • 缓存未击中插入时间: nv_cache_miss_insertion_duration_per_model,不解释,类似上面。

为服务配置合适的实例数量

为服务配置合适的实例数量,需要综合考虑GPU占用,CPU利用率的变化情况以及服务内部模型以及python_backend之间服务速度以及关系。
举例说明:
模型说明,这是一个通用文字识别服务,入口调用接口为text_server_normal,内部顺序调用了文字检测python接口text_detection_craft和文字识别的python接口text_recognition_cn.因为采用BLS书写,因此上面提到的三个接口中都是python的前后处理流程,也就是在cpu上运行的。text_detection_craft接口会调用text_detection_craft_model这个文字检测模型;text_recognition_cn会调用text_recognition_cn_model这个文字识别模型,这两个模型都是在GPU上运行的。
目录结构如下所示
tritonserver的metrics参数说明_第1张图片
当开启服务的时候,triton启动的服务列表如下所示:
tritonserver的metrics参数说明_第2张图片统统计一下压力测试之后,metrics上的指标如下:
locust统计信息以及metrics统计信息
首先所有的实例数量都配置为1,locust的压力测试我的初始配置为4个客户端访问,访问时间为2min;这两分钟一共处理了254个完整的通用文字服务,吞吐量为2.11req/s. 后面的两列是metrics统计的信息。

请求处理时间

上表中的第6列为我自行摘录的metrics统计信息,metrics上的数据用微秒计算单位,我这边换成了秒为单位。
请求时间包括CPU/GPU在各个接口上的计算时间。设置了多个instance,那么这里的处理时间还是默认包含CPU调度和GPU调度开销的时间。因此在运行的时候,需要关注一下CPU的利用率,如果利用率过载了,那么这个请求时间会因为CPU的卡调度算法而导致时间开销较长,我们在配置的时候应该尽量避免CPU过载的情况。

面对上面这样展示的请求时间开销,应该怎么分析?

因为主入口为text_server_normal,且内部不存在多线程的调用,是顺序调用的。需要等待文字检测和文字识别都完成之后才会处理后面一个请求,因此这里的排队时间都集中在主接口上,这很正常。这里主要关注一下每个模块的时间开销:
文字检测模型text_detection_craft_model的时间开销最小为6,文字检测的后处理开销为29,为了尽量减小调度时间,文字检测前后处理的实例数量设置为2倍比较合适。
在这里请求的图片中包含了25个文本框,因此一次文字检测服务后续需要25次文字识别服务,一般正常的文本图片也基本是这个情况。可以看到文字识别模型的服务时间是文字检测的8倍,文字识别前后处理和文字识别的时间类似。考虑到减少调度时间和避免CPU过载影响效率,设置这两个接口的instance数量为3倍。(虽然两个处理时间相差倍数很大,按照直觉应该成倍配置,但是实际测试发现如果真的设置成4个instance以上的配置,那么CPU时间片大概率会过载)
所有的请求都需要从入口函数text_server_normal进入,因此这里的instance数量也设置为3。
如此设置之后,进行压力测试:(注意,在压力测试的过程中,需要关注服务器的GPU显存利用率和CPU显存的利用率,如果CPU过载了,这会导致调度时间占请求时间的比率较大,不是一个合适的配置,需要降低instance的配置或者GPU长时间在100%)。
tritonserver的metrics参数说明_第3张图片
在top指令中可以看到tritonserver和triton_python_backend的CPU计算资源占用情况,当设置的instance数量过大的时候,过载问题就比较突出。

排队时间

排队时间就是在真正进入接口之前,请求在队列中的时间。
在所有的instance为1的配置中,我们发现排队时间主要集中在入口函数中。在后面的配置中,扩大入口函数的instance数值,就会观察到新的堵塞点。通过调高阻塞点接口的instance数值就可以寻找到更优的性能点。
需要注意的是,随着所有接口的instance数量的提高,很可能会导致CPU过载,导致整个服务的访问性能变差。因此需要观察CPU的计算占用情况。适当调整。

注意事项以及总结

服务的吞吐量和什么配置相关?

  1. 首先肯定和模型的运行速度相关;选择计算量更加小的模型
  2. 和CPU上的python处理脚本相关,如果有很多图像前后处理操作,那么速度会慢一点;
  3. 需要合适比率的配置,因为堵塞点可能会不停变化,需要寻找到比较稳定的参数配置,这个参数配置既能够减少系统的排队时间,又不会因为CPU的过载导致请求处理时间变长。
  4. 压测系统的客户数量,压测中需要充分测试接口的性能,一般从4U到8U进行测试。

参考文章

Metrics官方文档

你可能感兴趣的:(python,开发语言,人工智能,数据分析)