作者:战鹏州  英特尔物联网行业创新大使

目录

1.1 AI推理程序性能评价指标

1.1.1 AI模型的推理性能

1.1.2 端到端的AI推理程序性能

1.2 异步推理实现方式

1.2.1 OpenVINO异步推理Python API

1.2.2 同步和异步实现方式对比

1.2.3 异步推理范例程序

1.3 结论


本文将介绍通过异步推理实现方式,进一步提升AI推理程序的性能。在阅读本文前,请读者先参考《基于OpenVINO™2022.2和蝰蛇峡谷优化并部署 YOLOv5模型》,完成OpenVINO开发环境的创建并获得yolov5s.xml模型,然后阅读范例程序yolov5_ov2022_sync_dGPU.py,了解了OpenVINOTM的同步推理程序实现方式。

1.1 AI推理程序性能评价指标

在提升AI推理程序的性能前,先要理解评估AI推理程序性能的指标是什么。我们常用时延(Latency)和吞吐量(Throughput)来衡量AI推理程序的性能。

  • 时延:测量处理一个单位数据的速度快不快
  • 吞吐量:测量一个单位时间里面处理的数据多不多

很多人都容易误认为时延低必然吞吐量高,时延高必然吞吐量低。其实不是这样,以ATM机取钱为例,假设一个人在ATM机取钱的速度是30秒,若A银行有两台ATM机,那么A银行的吞吐量为4人/分钟,时延是30秒;若B银行有4台ATM机,那么B银行的吞吐量为8人/分钟,时延是30秒;若C银行有4台ATM机,并且要求每个人取完钱后,必须填写满意度调查表,大约花费30秒,那么C银行的吞吐量为8人/分钟,时延为1分钟。

由此可见,时延评估的是单一事件的处理速度,吞吐量评估的是整个系统处理事件的效率。时延高低跟吞吐量大小有关系,但不是直接的线性关系,我们需要同时着眼于时延和吞吐量这两个指标去优化。

另外,AI推理性能评价还有两个常见的场景,一个是单纯评价AI模型的推理性能,另一个是整体评价从采集数据到拿到最终结果的端到端的AI推理程序性能。

1.1.1 AI模型的推理性能

在单纯评价AI模型的推理性能的场景中:

  • 时延具体指讲数据输入AI模型后,多长时间可以从AI模型拿到输出结果
  • 吞吐量具体指在单位时间能完成多少数据的AI推理计算

[注意]在单纯评价AI模型的推理性能的场景中,数据的前处理和后处理所花费的时间不包含在时延和吞吐量的计算里面。

具体到计算机视觉应用场景的AI推理计算性能,吞吐量可以用单位时间内能完成多少张图片的AI推理计算来衡量,即FPS(Frame Per Second),如下图所示。

OpenVINO自带的性能评测工具的benchmark_app,主要用于单纯评价AI模型推理性能的场景。在蝰蛇峡谷平台上,使用命令:

benchmark_app -m yolov5.xml -d GPU.1

可以获得yolov5.xml模型在英特尔A770M独立显卡(GPU.1)上的推理性能,如下图所示。

1.1.2 端到端的AI推理程序性能

当AI模型集成到应用程序中后,对用户来说,更加关注的是从采集图像数据到拿到最终结果的端到端的性能,例如,用手机拍了一个水果,用户更在乎的是需要多少时间能展示出这个水果是什么。

一个典型端到端AI推理计算程序流程:

  1. 采集图像并解码
  2. 根据AI模型的要求,对图像数据做预处理
  3. 将预处理后的数据送入模型,执行推理计算
  4. 对推理计算结果做后处理,拿到最终结果

参考yolov5_ov2022_sync_dGPU.py的代码片段

# Acquire or load image
frame = cv2.imread("./data/images/zidane.jpg")
# preprocess frame by letterbox
letterbox_img, _, _= letterbox(frame, auto=False)
# Normalization + Swap RB + Layout from HWC to NCHW
blob = cv2.dnn.blobFromImage(letterbox_img, 1/255.0, swapRB=True)
# Step 3: Do the inference
outs = torch.tensor(net([blob])[output_node])
# Postprocess of YOLOv5:NMS
dets = non_max_suppression(outs)[0].numpy()
bboxes, scores, class_ids= dets[:,:4], dets[:,4], dets[:,5]
# rescale the coordinates
bboxes = scale_coords(letterbox_img.shape[:-1], bboxes, frame.shape[:-1]).astype(int)

用yolov5_ov2022_sync_dGPU.py中同步实现方式,可以看到在第1,2,4步时,AI推理设备是空闲的,如下图所示:

若能提升AI推理设备的利用率,则可以提高AI程序的吞吐量。提升AI推理设备利用率的典型方式,是将同步推理实现方式更换异步推理实现方式。

1.2 异步推理实现方式

异步推理实现方式是指在当前帧图片做AI推理计算时,并行启动下一帧图片的图像采集和图像数据预处理工作,使得当前帧的AI推理计算结束后,AI计算设备可以不用等待,直接做下一帧的AI 推理计算,持续保持AI计算设备繁忙,如下图所示:

使用benchmark_app工具,并指定实现方式为同步(sync)或异步(async),观察性能测试结果,异步方式的确能提高吞吐量,如下图所示:

benchmark_app -m yolov5.xml -d GPU.1 -api sync
benchmark_app -m yolov5.xml -d GPU.1 -api async

1.2.1 OpenVINO异步推理Python API

OpenVINOTM Runtime提供了推理请求(Infer Request)机制,来实现在指定的推理设备上以同步或异步方式运行AI模型。

在openvino.runtime.CompiledModel类里面,定义了create_infer_request()方法,用于创建openvino.runtime.InferRequest对象。

infer_request = compiled_model.create_infer_request()

当infer_request对象创建好后,可以用:

  • set_tensor(input_node, input_tensor):将数据传入模型的指定输入节点
  • start_async():通过非阻塞(non-blocking)的方式启动推理计算。
  • wait():等待推理计算结束
  • get_tensor(output_node):从模型的指定输出节点获取推理结果

1.2.2 同步和异步实现方式对比

同步实现方式伪代码

异步实现方式伪代码

创建一个负责处理当前帧的推理请求即可

... ...

While True:

采集当前帧图像

对当前帧做预处理

调用infer(),以阻塞方式启动推理计算

对推理结果做后处理

显示推理结果

创建一个推理请求负责处理当前帧

创建一个推理请求负责处理下一帧

... ...

采集当前帧图像

对当前帧做预处理

调用start_async(),以非阻塞方式启动当前帧推理计算

While True:

采集下一帧

对下一帧做预处理

调用start_async(),以非阻塞方式启动下一帧推理计算

调用wait(),等待当前帧推理计算结束

对当前帧推理结果做后处理

交换当前帧推理请求和下一帧推理请求

1.2.3 异步推理范例程序

根据异步实现方式伪代码,YOLOv5的异步推理范例程序的核心实现部分如下所示:

完整范例代码请下载:yolov5_ov2022_async_dGPU.py,

...
# Step 3. Create 1 Infer_request for current frame, 1 for next frame
# 创建一个推理请求负责处理当前帧
infer_request_curr = net.create_infer_request()
# 创建一个推理请求负责处理下一帧
infer_request_next = net.create_infer_request()
...
# Get the current frame,采集当前帧图像
frame_curr = cv2.imread("./data/images/bus.jpg")
# Preprocess the frame,对当前帧做预处理
letterbox_img_curr, _, _ = letterbox(frame_curr, auto=False)
# Normalization + Swap RB + Layout from HWC to NCHW
blob = Tensor(cv2.dnn.blobFromImage(letterbox_img_curr, 1/255.0, swapRB=True))
# Transfer the blob into the model
infer_request_curr.set_tensor(input_node, blob)
# Start the current frame Async Inference,调用start_sync(),以非阻塞方式启动当前帧推理计算
infer_request_curr.start_async()
while True:    # Calculate the end-to-end process throughput.start = time.time()# Get the next frame,采集下一帧frame_next = cv2.imread("./data/images/zidane.jpg")# Preprocess the frame,对下一帧做预处理letterbox_img_next, _, _ = letterbox(frame_next, auto=False)# Normalization + Swap RB + Layout from HWC to NCHWblob = Tensor(cv2.dnn.blobFromImage(letterbox_img_next, 1/255.0, swapRB=True))  # Transfer the blob into the modelinfer_request_next.set_tensor(input_node, blob)# Start the next frame Async Inference,调用start_sync(),以非阻塞的方式启动下一帧推理计算infer_request_next.start_async()# wait for the current frame inference result,调用wait(),等待当前帧推理计算结束infer_request_curr.wait()# Get the inference result from the output_nodeinfer_result = infer_request_curr.get_tensor(output_node)# Postprocess the inference result,对当前帧推理结果做后处理data = torch.tensor(infer_result.data)# Postprocess of YOLOv5:NMSdets = non_max_suppression(data)[0].numpy()bboxes, scores, class_ids= dets[:,:4], dets[:,4], dets[:,5]# rescale the coordinatesbboxes = scale_coords(letterbox_img_curr.shape[:-1], bboxes, frame_curr.shape[:-1]).astype(int)# show bbox of detectionsfor bbox, score, class_id in zip(bboxes, scores, class_ids):color = colors[int(class_id) % len(colors)]cv2.rectangle(frame_curr, (bbox[0],bbox[1]), (bbox[2], bbox[3]), color, 2)cv2.rectangle(frame_curr, (bbox[0], bbox[1] - 20), (bbox[2], bbox[1]), color, -1)cv2.putText(frame_curr, class_list[class_id], (bbox[0], bbox[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, .5, (255, 255, 255))end = time.time() # show FPSfps = (1 / (end - start)) fps_label = "Throughput: %.2f FPS" % fpscv2.putText(frame_curr, fps_label, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)print(fps_label+ "; Detections: " + str(len(class_ids)))cv2.imshow("Async API demo", frame_curr)# Swap the infer request,交换当前帧推理请求和下一帧推理请求infer_request_curr, infer_request_next = infer_request_next, infer_request_currframe_curr = frame_nextletterbox_img_curr = letterbox_img_next

请读者下载:yolov5_ov2022_async_dGPU.py 和 yolov5_ov2022_sync_dGPU.py,并放入yolov5文件夹中,然后分别运行。

下面是上述两个程序在蝰蛇峡谷上的运行结果截图,可以清晰的看到异步推理程序的吞吐量明显高于同步推理程序

1.3 结论

使用OpenVINO Runtime的异步推理API,将AI推理程序改造为异步推理的实现方式,可以明显的提升AI推理程序的吞吐量。

在蝰蛇峡谷上实现YOLOv5模型的OpenVINO异步推理程序相关推荐

  1. (六)使用Coral USB Accelerator在Raspberry Pi上部署YOLOv5模型

    目录 介绍 Raspberry Pi的初始步骤 准备目录并创建虚拟环境 在Raspberry Pi上安装TFLite解释器和PyTorch 在Raspberry Pi上安装Coral USB Acce ...

  2. 基于OpenVINOTM2022.2和蝰蛇峡谷优化并部署YOLOv5模型

    文章作者 英特尔物联网行业创新大使 杨雪锋 博士 中国矿业大学机电工程学院副教授: 发表学术论文30余篇,获国家专利授权20多件(其中发明专利8件) 目录 1.1 OpenVINOTM 2022.2简 ...

  3. 在英特尔独立显卡上部署YOLOv5 v7.0版实时实例分割模型

    作者:贾志刚 英特尔物联网创新大使 目录 1.1 YOLOv5实时实例分割模型简介 1.2 英特尔®消费级锐炫™ A 系列显卡简介 1.3  在英特尔独立显卡上部署YOLOv5-seg模型的完整流程 ...

  4. (四)训练用于口罩检测的YOLOv5模型

    目录 介绍 准备训练和验证数据 在Colab Notebook上训练YOLOv5模型 在Google Colab上测试模型 下一步 在这里,我们将训练和测试用于口罩检测的YOLOv5模型. 介绍 在本 ...

  5. win10环境下基于OpenVINO部署yolov5模型

    以在Intel的OpenVINO上部署Yolov5模型为例,加深对模型部署的理解. 1. 训练准备 获取yolov5模型及数据集 git clone git://github.com/ultralyt ...

  6. OpenVINO 2022.3实战六:NNCF 实现 YOLOv5 模型 INT8 量化

    OpenVINO 2022.3实战六:NNCF 实现 YOLOv5 模型 INT8 量化 1 将YOLOv5模型转换为OpenVINO IR 使用OpenVINO模型优化器将YOLOv5模型转换为Op ...

  7. 【全流程】从头在树莓派4B上部署自己训练的yolov5模型(配合NCS2加速)

    目录 0.前言 1.我的环境 2.整个流程 3.具体过程 3.1 训练自己的yolov5模型 3.2 将.pt模型转换为.onnx模型 3.3 在本地将.onnx转换成IR模型 3.4 在树莓派4B上 ...

  8. 租用服务器,以及部署在pycharm专业版上的pytorch环境训练yolov5模型教程服务器环境安装库文件:

    租用服务器,以及部署在pycharm专业版上的pytorch环境训练yolov5模型教程服务器环境安装库文件: 一.租用服务器选择环境: 1. 租用服务器网站 2. 选择1.8的pytorch环境,点 ...

  9. 在英特尔独立显卡上训练TensorFlow模型

    作者:武卓,张晶 目录 1.1 英特尔锐炫™独立显卡简介 1.2 蝰蛇峡谷简介 1.3 搭建训练TensorFlow模型的开发环境 1.3.1 Windows 版本要求: 1.3.2 下载并安装最新的 ...

最新文章

  1. OvS、OvS-DPDK、VPP 基准性能对比
  2. vim 居中光标所在行(转载)
  3. java socket/Serversocket编程详解(中/英文)
  4. Safe or Glitch-Free Clock Gating
  5. 信息学奥赛一本通(1245:不重复地输出数)
  6. sql ntext 替换存储过程
  7. mybatis使用经验
  8. 继续发布分页类的BLL层和Interface层部分哈
  9. 用纯JSP实现按条件查询数据库
  10. tenrrt编译出错
  11. 动态调用Webservice 支持Soapheader身份验证(转)
  12. chmod 777命令_Linux shell命令总结
  13. 好用的文件批量改名工具推荐
  14. Unity单例模式+例子
  15. 显卡刷bios改型号_A卡修改BIOS软件/刷显卡BIOS软件
  16. TextCNN模型原理
  17. ~囍~ 将欢乐进行到底篇
  18. 二分法和黄金分割法的区别和联系,附Python代码
  19. 【系列笔记一】-USYD悉尼大学Data1002 Grok Module 3 课件 作业 assignment讲解
  20. 文件批量改名-bat操作

热门文章

  1. 商品收藏模块的功能设计实现
  2. 这个方法可以让你的代码高出一个逼格——掌握 Java Stream 流操作
  3. react上下文_了解React的新上下文API
  4. 管理信息系统案例分析_【案例】MES系统助力华联电子仓库工作人员效率提高30%...
  5. 【一本通 1373】鱼塘钓鱼(fishing)【堆】
  6. 奇数层PCB板为何在PCB多层板中几乎没有见到呢?
  7. 将两个有序数组合并到一起
  8. 斐波那契Fibonacci 算法优化
  9. 抄笔记:尤雨溪在Vue3.0 Beta直播里聊到了这些…
  10. 大数据入门,你需要懂这四个常识