前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何基于OpenVINO加速飞桨模型推理?

如何基于OpenVINO加速飞桨模型推理?

作者头像
用户1386409
发布2021-11-17 14:20:13
发布2021-11-17 14:20:13
1.2K00
代码可运行
举报
文章被收录于专栏:PaddlePaddlePaddlePaddle
运行总次数:0
代码可运行

关于OpenVINO x 飞桨

OpenVINO是英特尔基于自身现有的硬件平台开发的一种工具套件,主要用于快速开发高性能计算机视觉及深度学习视觉的应用程序和解决方案,从而实现人类视觉模拟、自动语音识别、自然语言处理和推荐系统任务。该工具套件基于最新一代的人工神经网络,包括卷积神经网络、递归网络和基于注意力的网络,可扩展跨英特尔硬件的计算机视觉和非视觉工作负载,从而最大限度地提高性能。基于OpenVINO,可提升应用程序在CPU计算设备上的推理速度。

在飞桨团队和OpenVINO团队的合作推进下,目前OpenVINO已支持直接导入飞桨模型格式进行模型优化转换和部署;而为了给开发者带去更好的体验,我们也正在开展将OpenVINO作为后端引擎向飞桨原生推理框架Paddle Inference以及轻量化推理引擎Paddle Lite的适配集成工作,待正式发布后用户即可亲自感受飞桨模型在OpenVINO上的无缝部署体验。

官方文档请访问:https://docs.openvino.ai/cn/latest/index.html

概述

本文以钢卷捆带检测项目为例,分享如何基于OpenVINO实现飞桨模型的CPU推理加速,主要包括:

  1. Windows及Linux平台下的OpenVINO源码编译;
  2. 如何产出飞桨模型直接用于在OpenVINO部署;
  3. 如何使用OpenVINO工具完成部署模型优化;
  4. CPU环境下的推理加速测试实验。

基于飞桨及OpenVINO进行项目开发的典型工作流程为:

(1)模型训练部分:

(2)模型转换及应用部分

搭建飞桨开发环境及模型训练

为了兼顾效率和精度,在实际案例中采用了PaddleDetection中的YOLOv3模型。PaddleDetection作为成熟的目标检测开发套件,提供了从数据准备、模型训练、模型评估、模型导出到模型部署的全流程。

受篇幅限制,本文只给出搭建飞桨环境的基本流程,请大家在安装以下项目时,详细参考相关官方文档。另外,本文提供了各项目的版本号,建议大家按照提供版本进行安装。

1.配置飞桨框架

安装CPU或GPU版本的飞桨,本文所安装的版本为paddlepaddle-gpu==2.1.3.post112,python版本为3.6.2。

代码语言:javascript
代码运行次数:0
运行
复制
python -m pip install paddlepaddle-gpu==2.1.3.post112 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html

2.配置PaddleDetection,本文所安装的版本为2.1.0

2.1安装pycocotools

PaddleDetection依赖pycocotools工具,所以需要提前安装。如果使用的是Windows系统,由于原版cocoapi不支持Windows,pycocotools依赖可能安装失败,可采用第三方实现版本,该版本仅支持Python3,本文所安装的pycocotools版本为2.0。

代码语言:javascript
代码运行次数:0
运行
复制
pipinstallgit+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI

如果使用的是Python <= 3.6的版本,安装pycocotools可能会报错:

报错信息:distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('cython>=0.27.3'),

可通过先安装cython,如pip install cython解决该问题。

2.2 安装PaddleDetection

官方文档推荐了以下两种方式进行安装,本文采用了方式一。

方式一:通过pip安装,pip安装方式只支持Python3

代码语言:javascript
代码运行次数:0
运行
复制
# pip安装PaddleDetection
pip install paddledet==2.1.0 -i https://mirror.baidu.com/pypi/simple
# 下载使用源码中的配置文件和代码示例
git clone https://github.com/PaddlePaddle/PaddleDetection.git
cd PaddleDetection

方式二:源码编译安装

代码语言:javascript
代码运行次数:0
运行
复制
# 克隆PaddleDetection仓库
cd <path/to/clone/PaddleDetection>
git clone https://github.com/PaddlePaddle/PaddleDetection.git
# 编译安装PaddleDetection
cd PaddleDetection
python setup.py install
# 安装其他依赖
pip install -r requirements.txt

3.模型训练及导出

Paddle Detection的开发套件很完善,因此模型的训练非常方便,官方教程有非常详细的指引。

模型训练可参考官方提供的教程:

“30分钟快速上手PaddleDetection”。

https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/docs/tutorials/GETTING_STARTED_cn.md

在进行模型训练时,损失函数、mAP等指标的变化情况也可通过VisualDL可视化工具监测。

在模型训练过程中保存的模型文件是包含前向预测和反向传播的过程,在实际的工业部署则不需要反向传播,因此需要将模型进行导出并转换成部署需要的模型格式。在PaddleDetection中提供了 tools/export_model.py脚本来导出模型。

需要注意的是,导出的预测模型包含了以下文件:

代码语言:javascript
代码运行次数:0
运行
复制
├── inference_model/yolov3
│   ├── infer_cfg.yml
│   ├── model.pdiparams
│   ├── model.pdiparams.info
│   └── model.pdmodel

在后文模型转换阶段,我们需要用的就是这个.pdmodel格式的模型文件。

OpenVINO源码编译

在使用OpenVINO前,首先需要以源码编译的形式安装,下面分别介绍Windows及Linux平台的编译过程。(推荐大家使用Linux平台,因为我在Windows下进行编译配置,遇到了很多坑。)

1.Windows平台编译

可参考官方文档:

https://github.com/openvinotoolkit/openvino/wiki/BuildingForWindows

1.1软件需求

  • CMake 3.13及以上 # 本文使用的版本为3.20。
  • Microsoft Visual Studio 2019, version 16.8 or later,确保C++ Cmake tool for Windows 已安装。
  • (可选项)Intel Graphics Driver for Windows (26.20)。
  • Python 3.6及以上,确保Python已被添加至环境变量。

1.2编译步骤

1)拉取OpenVINO的source安装包

代码语言:javascript
代码运行次数:0
运行
复制
git clone https://github.com/openvinotoolkit/openvino.git

2)进入OV目录

代码语言:javascript
代码运行次数:0
运行
复制
cd openvino

3)下载所需的sub模块

代码语言:javascript
代码运行次数:0
运行
复制
git submodule update --init --recursive

4)创建 build 文件夹

代码语言:javascript
代码运行次数:0
运行
复制
mkdir build

5)进入build目录

代码语言:javascript
代码运行次数:0
运行
复制
cd build

6)创建cmake文件(如果此步失败,重新执行前请务必把build文件夹里的生成文件清除)注意加粗处需修改。

代码语言:javascript
代码运行次数:0
运行
复制
cmake -CMAKE_USE_WIN32_THREADS_INIT=0N -DNGRAPH_PDPD_FRONTEND_ENABLE=ON -DENABLE_SAMPLES=OFF -DENABLE_CLDNN=OFF -DENABLE_PYTHON=ON -DNGRAPH_PYTHON_BUILD_ENABLE=ON -DNGRAPH_ONNX_IMPORT_ENABLE=ON    -DCMAKE_INSTALL_PREFIX="D:\Openvino\openvino\build\install" -DNGRAPH_UNIT_TEST_ENABLE=ON -DNGRAPH_USE_SYSTEM_PROTOBUF=OFF -DPYTHON_EXECUTABLE="D:\Anaconda3\envs\ov\python.exe" -DPYTHON_LIBRARY="D:\Anaconda3\envs\ov\libs\python36.lib" -DPYTHON_INCLUDE_DIR="D:\Anaconda3\envs\ov\include" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DENABLE_GNA=OFF -DENABLE_CLANG_FORMAT=ON  -DENABLE_TESTS=ON -DENABLE_FUNCTIONAL_TESTS=ON -DENABLE_STRICT_DEPENDENCIES=OFF   -DENABLE_MYRIAD=OFF -DENABLE_FASTER_BUILD=ON  -DDNNL_LIBRARY_TYPE=SHARED  -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release ..

其中:

代码语言:javascript
代码运行次数:0
运行
复制
-DPYTHON_EXECUTABLE="C:\Users\abc\AppData\Local\Programs\Python\Python36\python.exe"
-DPYTHON_LIBRARY="C:\Users\abc\AppData\Local\Programs\Python\Python36\libs\python36.lib"
-DPYTHON_INCLUDE_DIR="C:\Users\abc\AppData\Local\Programs\Python\Python36\include"

以上需要根据你的python安装路径进行修改为你的路径。

代码语言:javascript
代码运行次数:0
运行
复制
-DCMAKE_INSTALL_PREFIX="C:\openvino\openvino\build\install"

以上需要修改为你的build的文件夹的位置。

若无报错,且显示如下,说明创建CMake文件成功:

- Configuring done

- Generating done

注意:若以上编译方式一直失败,无法解决问题,可尝试使用只加python相关参数进行编译。

代码语言:javascript
代码运行次数:0
运行
复制
cmake -DENABLE_PYTHON=ON -DNGRAPH_PYTHON_BUILD_ENABLE=ON -DPYTHON_EXECUTABLE="D:\Anaconda3\envs\ov\python.exe" -DPYTHON_LIBRARY="D:\Anaconda3\envs\ov\libs\python36.lib" -DPYTHON_INCLUDE_DIR="D:\Anaconda3\envs\ov\include"  -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release ..

7)编译

代码语言:javascript
代码运行次数:0
运行
复制
cmake --build . --config Release --verbose -j8

j后面的数字需要根据自己电脑CPU核数来修改,本文所用电脑为8核。

如果编译过程中遇到中文字符不可识别的报错问题,定位到源码中的相关行,把报错的中文字符行直接注释掉即可。

编译完成后只要是没有报错(红色error),应该就是成功了。编译过程中会有大量的警告(黄色warning),忽略即可。

8)添加至环境变量

将以下路径添加至系统环境变量中,以便OpenVINO能找到他们:

  • <openvino_repo>/inference-engine/temp/tbb/bin
  • <openvino_repo>/inference-engine/temp/opencv_4.5.0/opencv/bin

9)初始化环境变量

进入到scripts/setupvars路径,在cmd中运行setupvars.bat,显示[setupvars.bat] OpenVINO environment initialized,则表示完成环境变量的初始化。

至此,Windows平台下的编译安装就完成了,可以使用OpenVINO了。

2.Linux平台编译

Linux下编译比较简单,建议直接参考官方文档,配置软件需求及进行编译:

https://github.com/openvinotoolkit/openvino/wiki/BuildingForWindows

1)按照官方文档1-4步骤进行

2)编译

按照指引进行操作,当进行到第5步cmake时,替换成如下的cmake参数(不需要自行修改,可直接运行)。

代码语言:javascript
代码运行次数:0
运行
复制
cmake -DNGRAPH_PDPD_FRONTEND_ENABLE=ON -DENABLE_SAMPLES=OFF -DENABLE_CLDNN=OFF -DENABLE_PYTHON=ON -DNGRAPH_PYTHON_BUILD_ENABLE=ON -DENABLE_MYRIAD=OFF -DNGRAPH_ONNX_IMPORT_ENABLE=ON -DCMAKE_INSTALL_PREFIX=`pwd`/install -DNGRAPH_UNIT_TEST_ENABLE=ON -DNGRAPH_USE_SYSTEM_PROTOBUF=OFF -DPYTHON_EXECUTABLE=$(which python3) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DENABLE_GNA=OFF -DENABLE_CLANG_FORMAT=ON -DENABLE_TESTS=ON -DENABLE_FUNCTIONAL_TESTS=ON -DENABLE_STRICT_DEPENDENCIES=OFF \
-DENABLE_FASTER_BUILD=ON \
-DDNNL_LIBRARY_TYPE=SHARED \

3)初始化环境变量

编译工作全部完成之后,进入到openvino/build/install/bin,运行Source setupvars.sh初始化环境变量。

至此,Linux平台下的编译安装也完成了,可以使用OpenVINO了。

模型转换

在Windows或Linux平台下配置好OpenVINO环境后,转换和测试脚本就可以使用了。下面介绍如何将飞桨的.pdmodel模型转换至OpenVINO的IR格式。

IR格式的模型,包含XML和BIN两个文件。

  • .xml 描述网络拓扑结构
  • .bin 包含模型权重及偏差的二进制数据

1.进入到openvino/model-optimizer路径

2.模型转换

目前OpenVINO对飞桨的支持度较好,无需中间格式转换,可通过mo.py脚本直接将飞桨模型转换成IR格式,需要我们做的就是指定模型类型、模型的输入输出、路径等各项参数,整个过程非常地高效和便捷。示例代码如:

代码语言:javascript
代码运行次数:0
运行
复制
python mo.py --model_name yolov3_mobilenet_v1_270e_coco \
--output_dir <PATH_TO_OUTPUT_DIR> \
--framework=paddle \
--data_type=FP32 \
--reverse_input_channels \
--input_shape=[2,3,608,608],[1,2],[1,2] \
--input=image,im_shape,scale_factor \
--output=save_infer_model/scale_0.tmp_1,save_infer_model/scale_1.tmp_1 \
--input_model= < PATH_TO_MODEL_DIR\model.pdmodel>

参数的含义及设置方法请参考:

https://github.com/openvinotoolkit/openvino/blob/master/docs/MO_DG/prepare_model/convert_model/Converting_Model_General.md

执行模型转换脚本mo.py后,输出如下图所示,表示成功生成IR格式的模型,包含XML和BIN两个文件。

推理加速测试

转换后的模型可以通过OpenVINO提供的C++或Python接口实现推理功能,这里提供了一个简单的示例。

代码语言:javascript
代码运行次数:0
运行
复制
import os, sys, os.path
os.environ['Path'] += r'D:\openvino\bin\intel64\Release\python_api\python3.6;'
import numpy as np
import cv2
from openvino.inference_engine import IENetwork, IECore, ExecutableNetwork

import time
import urllib, shutil, json
import yaml
from yaml.loader import SafeLoader

## 图像处理
def image_preprocess(input_image, size):
    img = cv2.resize(input_image, (size,size))
    img = np.transpose(img, [2,0,1]) / 255
    img = np.expand_dims(img, 0)
    ##NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}
    img_mean = np.array([0.485, 0.456,0.406]).reshape((3,1,1))
    img_std = np.array([0.229, 0.224, 0.225]).reshape((3,1,1))
    img -= img_mean
    img /= img_std
    return img.astype(np.float32)

## 绘制矩形框
def draw_box(img, results, label_text, scale_x, scale_y):
    for i in range(len(results)):
        #print(results[i])
        bbox = results[i, 2:]
        label_id = int(results[i, 0])
        score = results[i, 1]
        if(score>0.20):
            xmin, ymin, xmax, ymax = [int(bbox[0]*scale_x), int(bbox[1]*scale_y), 
                                      int(bbox[2]*scale_x), int(bbox[3]*scale_y)]
            cv2.rectangle(img,(xmin, ymin),(xmax, ymax),(0,255,0),3)
            font = cv2.FONT_HERSHEY_SIMPLEX
            label_text = label_list[label_id];
            cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0,255,0), 2)
            cv2.putText(img, label_text + ":" + str(score) ,(xmin,ymin+50), font, 1.5,(255,255,255), 2,cv2.LINE_AA)
    return img

device = 'CPU'
ie = IECore() 
yolov3_path = r"C:\Users\uzel\Desktop\openvino_workspace\mo_output\yolov3_mobilenet_v1_091511.xml" #指定模型路径
net = ie.read_network(yolov3_path)

exec_net = ie.load_network(net, "CPU")

label_list = []
pdmodel_config = r"C:\Users\uzel\Desktop\openvino_workspace\mo_output\infer_cfg.yml"
with open(pdmodel_config) as f:
    data = yaml.load(f, Loader=SafeLoader)
label_list = data['label_list']

input_image = cv2.imread(r"C:\Users\uzel\Desktop\openvino_workspace\demo\images\Image__2021-05-14__10-28-55.bmp")
test_image = image_preprocess(input_image, 608)
test_im_shape = np.array([[608, 608]]).astype('float32')
test_scale_factor = np.array([[1, 2]]).astype('float32')

inputs_dict = {'image': test_image, "im_shape": test_im_shape,
               "scale_factor": test_scale_factor}

start_time = time.time() 
output = exec_net.infer(inputs_dict)
end_time = time.time() 
print("time: %.2f ms"  % (1000 * (end_time-start_time)) )
time = str(np.round(1000 * (end_time-start_time))) + "ms"
cv2.putText(input_image, "cost time :" + time ,(20,50), cv2.FONT_HERSHEY_SIMPLEX, 2,(0,0,0), 2,cv2.LINE_AA)

result_ie = list(output.values())
result_image = draw_box(input_image, result_ie[0], label_list,input_image.shape[1]/608*2, input_image.shape[0]/608*2)

cv2.imwrite("test.png", result_image)

检测结果如下图所示:经过OpenVINO加速,基于YOLOv3模型的钢卷捆带监测方案,在推理速度上约有一倍的提升(优化前每batch为~1000ms,优化后可以提升至~400ms),而精度与原始结果也基本持平。

至此,基于OpenVINO实现飞桨模型的CPU推理加速就全部介绍完了。大家可结合自己具体的业务需求,按照上述步骤完成模型转换,并将模型部署至英特尔CPU计算设备上。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PaddlePaddle 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档