栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

VS2019使用C++调用并部署pytorch模型全过程(libtorch+opencv)(cpu+gpu)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

VS2019使用C++调用并部署pytorch模型全过程(libtorch+opencv)(cpu+gpu)

环境配置vs2019+libtorch1.9.0+opencv3.4.2+cuda11.0+cudnn8.0(实测可用,不踩坑) 须知

Libtorch版本需与pytorch版本兼容(最好一致),系统下载与pytorch版本相同的CUDA和Cudnn,否则导入模型将出错。
若想使程序在GPU上运行,需下载GPU版libtorch,其也支持cpu运行。
文中给出图片或许版本与标题不一致,不影响实际操作,作者已亲测可行

libtorch

用C++调用pytorch模型,其目的在于:使用C++及多线程可以加快模型预测速度

模型训练有两种方法:
1.直接使用C++编写训练代码,搭建完整的网络模型,但此方法无法使用迁移学习,而迁移学习是目前训练样本几乎都会用到的方法
2.使用python代码训练好模型,使用JIT技术,将python模型导出为C++可调用的模型

Torchscript:一种从PyTorch代码创建可序列化和可优化模型的方法。用Torchscript编写的任何代码都可以从Python进程中保存并加载到没有Python依赖关系的进程中。
利用工具可增量地将模型从纯Python程序转换为能够独立于Python运行的Torchscript程序,例如,一个独立的c++程序。

实验流程 1.安装librtorch(有gpu和cpu版本,都可实现)

[1] pytorch官网.

[2] 某博主整理的libtorch各版本下载地址.!

2.安装opencv

opencv官网.
官网下载opencv库压缩包,解压至本地

3.python端:

(1)搭建pytorch网络模型

(2)将PyTorch模型转换为Torch script Module
第一个方法是tracing。该方法通过将样本输入到模型中一次,来对该过程进行评估从而捕获模型结构,并记录该样本在模型中的flow。该方法适用于模型中很少使用控制flow的模型。
第二个方法就是向模型添加显式注释,通知Torch script编译器它可以直接解析和编译模型代码,受Torch script语言强加的约束。

利用Tracing将模型转换为Torch script (无论后续选择用cpu或gpu,此步操作相同)
要通过tracing来将PyTorch模型转换为Torch脚本,必须将模型的实例以及样本输入传递给torch.jit.trace函数,并在模块的forward方法中嵌入模型评估的跟踪,这将生成一个torch.jit.scriptModule对象,最后将该对象保存(即将scriptModule序列化为一个文件。然后,C++就可以不依赖任何Python代码来执行该script所对应的Pytorch模型。)。

【导入模型:(按照自己保存模型的方式进行导入–直接保存模型or保存权重参数)】

【提供任意输入张量(size需符合网络输入要求):】

【将输入送入网络,追踪模型所有操作】
序列化模型时,模型和输入在cpu上运算

【保存序列化后模型:】

跟踪的scriptModule可以与常规PyTorch模块进行相同的计算

3.C++端

(1)在VS中配置libtorch库
创建新项目;
配置头文件(项目->属性);

配置库目录;

添加依赖库的文件名(此处为确保libtorch的所有相关lib文件被导入,可写为~lib*.lib)

tips:

(2)在VS(2019)中配置opencv库
Vc++目录>包含目录:~OpenCVbuildinclude
~OpenCVbuildincludeopencv
~OpenCVbuildincludeopencv2
>库目录: ~OpenCVbuildx64vc15lib

链接器>附加依赖项: opencv_world342d.lib (对应debug)
opencv_world342.lib (对应release)

(3)在C++中加载和执行script Module
要在C ++中加载序列化的PyTorch模型,必须依赖于PyTorch C ++ API - 也称为LibTorch。
即创建最终调用网络模型.cpp文件;(cpu运行可直接在新项目中创建,gpu运行需单独创建)
【导入头文件】

【载入模型】
模型路径中必须是’\’;路径中可以有中文(但一般路径最好不用中文!),必须是绝对路径;

*argv[[1]]为序列化后模型的路径

【执行模型】

创建一个torch :: jit :: IValue的向量并添加一个输入。
要创建输入张量,我们使用torch :: ones(),相当于C ++ API中的torch.ones。


然后运行script::Module的forward方法,将我们创建的输入向量传递给它。最后调用toTensor()将其转换为张量。

(4)LibTorch构建应用程序(生成.exe文件)
【CPU版本:】
可在vs中直接创建项目,在项目中创建.cpp文件,再直接点击运行进行调试
【GPU版本:】
先创建.cpp文件,再配置CMakeLists.txt来建立项目,最后在cmd中通过cmake编译项目,生成.exe可执行程序。如下:
1、执行(3),将代码保存到名为main.cpp的文件中。

2、构建它的CMakeLists.txt

cmake_minimum_required(VERSION 3.0 )   # 指定cmake的最小版本
project(gpucode)     # 设置项目名称

SET(CMAKE_BUILE_TYPE Debug)
 
find_package(Torch REQUIRED)

set(OpenCV_DIR D:/opencv3.4.2/build)
set(OpenCV_MODULE_PATH D:/opencv3.4.2/build)
find_package(OpenCV REQUIRED)

include_directories( ${OpenCV_INCLUDE_DIRS} )
include_directories( ${Torch_INCLUDE_DIRS} )

message(STATUS "Pytorch status:")
message(STATUS "    libraries: ${TORCH_LIBRARIES}")
message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

add_executable(gpucode main.cpp)  # 生成可执行文件  
target_link_libraries(gpucode "${TORCH_LIBRARIES}" "${OpenCV_LIBS}")    # 设置 target 需要链接的库
set_property(TARGET gpucode PROPERTY CXX_STANDARD 11)

构建应用程序时,假设我们的目录布局如下:

		F:/C++code/gpucode1/
		    CMakeLists.txt
		    main.cpp

3、CMD中运行以下命令从gpucode/文件夹中构建应用程序:

cd "F:C++codegpucode1"

再输入:

cmake -DCMAKE_PREFIX_PATH="F:C++codegpucode1"

DCMAKE_PREFIX_PATH:该路径为生成项目的位置,路径下需包含CMakeLists.txt

make           

【make可用cmake --build . --config Debug/Release替代,(Debug/Release具体看自己的C++代码选择的调试模式),效果一致】

如果一切顺利,它将出现以下语句:

➀ Cmake-DCMAKE_PREFIX_PATH="F:C++codegpucode1"


➁ cmake --build . --config Debug

4.结果比较

使用相同的序列化模型(.pt文件)通过libtorch在vs上运行来尝试。通过比较,发现C++端的输出与Python端的输出是一样的,表明实验成功。
运行gpucode.exe文件:

Pycharm运行.py文件:

常见问题

1.利用cpu运行时,占用率太高

2.验证c++端gpu是否可用
std::cout << torch::cuda::is_available() << std::endl;
返回值=1,即可。为0表示显卡未调用起来

/INCLUDE:?warp_size@cuda@at@@YAHXZ

(将原有的%(AdditionalOptions) /machine:x64)删除)



初次应用GPU时,会有预热过程,耗时较长

3.GPU版编译成功,但运行到model.to(at::KCUDA)报错或无反应
[[1]]检查GPU是否能够成功调用
[[2]]检查是否按照教程利用cmake进行编译,不可直接在vs软件进行调试

4.torch::jit::load()导入模型运行无反应或导入失败
[[1]]序列化模型时,模型和输入不需指定在gpu上进行计算
即不需有下语句:
device=”gpu” ; model=model.to(device) ;x=x. cuda()
[[2]]检查训练py网络模型的pytorch版本是否和libtorch版本一致
[[3]]尝试利用cmake进行编译

5.报错找不到.dll文件
检查配置环境,若仍无法解决,则将缺失dll文件直接复制于项目目录下(或.exe所在目录下)

6.报错无法定位程序输入点于动态链接库 .exe上

[[1]].检查项目路径中是否有中文
[[2]].是否在利用cmake生成可执行文件前,在vs中进行了调试(即点击了本地windows调试器)?
----清理已生成的解决方案,再重新用cmake编译
----若上无效,建议重新创建项目

7.cmake报错opencv not found

用记事本打开路径对应的OpenCVConfig.cmake文件,修改最后 OpenCV_FOUND为TRUE

8.比较cpu和gpu运算时间差异
c++端:

	#include
	double start= GetTickCount();    //得到系统运行时间 单位为ms
	double  end = GetTickCount();

python端:

	import time
	starttime = time.time()
	endtime = time.time()
	time = endtime - starttime

9.找不到libtorch的配置文件

在Cmakelists.txt中find_package(Torch REQUIRED)前面加入下语句:

路径为上述配置文件所在文件夹的绝对路径

10.无法解析的外部函数
cpu:检查项目–>属性–>链接库配置,重新生成解决方案
gpu:检查项目–>属性–>链接库配置,重新执行cmake第二步。若修改后重新运行问题依然存在,则在vs中先清理解决方案,再在cmd中重新cmake

------tbc-------

【作者有话说】
以上内容仅为博主自主整理分享,很多内容也是来源于网络,若有侵权,请私聊告知
大家有任何问题可在评论区讨论交流~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/321329.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号