YOLOV8兼容适配昇腾NPU_V2(解决310P3 推理卡上加载慢问题)
背景:
在310P3 的推理卡上,使用原先的torch_npu和torchvision_npu插件,虽然可以调用模型进行推理,
但是会出现YOLOV8 模型权重加载特别慢的问题(5-10分钟),并且推理时候会出现参数切换后,
模型推理再次缓慢问题。并且通过npu-smi info 观察可知,npu的处理性能损耗还是特别高的。
通过询问昇腾技术支持可知,由于910和310P3沿用的不同架构的训练卡和推理卡,
所以torch_npu和torchvision_npu插件在310P3上的时候可能出现不完全兼容问题。
对此提供了一些硬编码织入兼容的方案,以下是对本次兼容做的一些适配总结。
对此,基于训练卡和推理卡,请结合使用适合方案。
文档(官方)
以上是官方提供的方案,但有以下两个问题:
- 当前让回退的torch版本是1.13.0,显然可以知道ultralytics包也得回退到旧版本(8.0.29),但旧版本和新版本差距较大,对于新版本训练好的模型,通过文档的验证方法无法正常调用,这是因为大版本的迭代,包路径和调用的方法参数都有所变化,新模型中解析出来的参数无法正常使用。基于各自业务系统的版本要求,也存在一定的版本不回退问题。
- 如果使用文档通过coco的验证数据集跑通过一次,就会发现提供的infer代码其实只是模型验证的调用,没有提供推理调用方法。
对此,不进行一定的业务改造和适配的话,是无法做到各自版本的调用推理的。
措施方案
通过根据ultralytics 8.0.29版本包和提供的infer代码进行分析,可知,当前使用的infer验证方法是基于ultralytics 8.0.29中目标检测的验证器进行代码抽离的改造,所以我们可以基于该代码的改造,应对自己的ultralytics 版本,提取抽离代码自己改造适配。
对于代码涉及的地方比较多,我就在此抽离部分代码说一些处理步骤逻辑:
- 使用昇腾的模型推理,前提需要安装好ais_bench推理工具 这块可以借鉴官网提供的文档进行依赖包的安装。
- 对于涉及的模型类别,需要抽离对应推理类别的相关的源码,然后进行兼容修改,主要涉及的是预处理的输入格式转换,调用昇腾推理工具推理还有后处理数据格式转换。
- 对于推理,在推理时使用昇腾API模型进行推理,涉及的torch需要切换为cpu形式,比如模型加载权重方法,nms方法调用等等都需要切换成cpu。
主要调用推理改造代码如下
# 当前代码是基于8.2.48,可以按照各自使用版本自己拉取源码修改
# 以目标检测为例,找到寻找stream_inference 方法,改造为如下形式
@smart_inference_mode()
def stream_inference(self, source=None, model=None, *args, **kwargs):
"""Streams real-time inference on camera feed and saves results to file."""
if self.args.verbose:
LOGGER.info("")
# Setup model
if not self.model:
self.setup_model(model)
# 【兼容】 使用昇腾的模型
om_model = self.om
# 创建例子如下:
# om_model_path = om
# device_id = device_id
# om_model = InferSession(int(device_id), om_model_path)
#
with self._lock: # for thread-safe inference
# Setup source every time predict is called
self.setup_source(source if source is not None else self.args.source)
# Check if save_dir/ label file exists
if self.args.save or self.args.save_txt:
(self.save_dir / "labels" if self.args.save_txt else self.save_dir).mkdir(parents=True, exist_ok=True)
# Warmup model
if not self.done_warmup:
self.model.warmup(imgsz=(1 if self.model.pt or self.model.triton else self.dataset.bs, 3, *self.imgsz))
self.done_warmup = True
self.