在蝰蛇峡谷上实现YOLOv5模型的OpenVINO异步推理程序
作者:戰鵬州 ?英特爾物聯網行業創新大使
目錄
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推理計算程序流程:
參考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 async1.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异步推理程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Echarts 做的温度计
- 下一篇: 基于大数据的高校生源可视化分析系统