点击小眼睛开启蜘蛛网特效

Pytorch的C++端(libtorch)在Windows中的使用

《Pytorch的C++端(libtorch)在Windows中的使用》

前言

填一个之前的坑啊,本篇的姊妹篇——利用Pytorch的C++前端(libtorch)读取预训练权重并进行预测 这篇文章中已经说明了如何在Ubuntu系统中使用libtorch做预测,当初也有朋友问我如何在Windows之下尝试使用libtorch,当时因为时间关系没有去看,后来就给忘了…现在有时间了当然要尝试一下~

当然先说结论哈,其实在Windows环境下的配置也是很简单的,因为官方已经替我们编译好的Windows版本的libtorch,这下就节省了我们编译Pytorch的时间,直接可以拿来使用,只要稍微配置一下就可以在Windows跑起libtorch了,没有想象中那么多的步骤,大可放心。

《Pytorch的C++端(libtorch)在Windows中的使用》

下文中使用的代码和之前在Ubuntu中使用的完全相同,我们不需要进行修改。

同样,首先,我们在官网下载适合于Windows的libtorch,因为稳定版出来了,所以我们可以直接拿来使用。有CPU版本的和GPU版本的,这里我都进行了测试,都是可以的直接使用的,大家按照自己的需求进行下载即可。

个人环境:

  • win10
  • cuda9.0 + cudnn7.0.5
  • 1060-6G

《Pytorch的C++端(libtorch)在Windows中的使用》

正式开始

与之前实现的任务相同,我这里将libtorch和OpenCV一起编译,使用OpenCV的读取摄像头然后识别当前的手势,模型是我自己训练好的,对于大家来说可以自己随便挑一个模型来使用。

下图为在Visual Studio中使用libtorch和OpenCV来实现判断剪刀石头布手势,运行的平台是cpu端。当然GPU端也是可以运行的,之后也会进行详解。

《Pytorch的C++端(libtorch)在Windows中的使用》

不得不说下,Pytorch的部署端真的很好用啊,虽然说目前仅仅适合一些小型的任务,但是潜力还是很大地,libtorch端配套Pytorch真的是太方便了!

获取libtorch

之前在Ubuntu跑libtorch的时候,因为OpenCV的一些原因,如果需要libtorch和OpenCV一起编译的话,最好自己编译一边libtorch从而保证libtorch和OpenCV混合编译时不会发生冲突。但是在win10端,OpenCV可以直接从官网下载已经编译好的,既然OpenCV从官方直接下载了,那么libtorch当然也从官方直接下载了。

正如前言所说,打开官网点击下载即可,CPU和GPU按照自己来进行选择。

测试GPU端的libtorch

在Windows端,因为我们从官方下载的OpenCV预编译版本是利用MSVS编译的,也就是我们常说的Visual Studio编译工具,所以我们接下来使用的编译器就是Visual Studio自带的编译器,为此我们需要安装:

  • Visual Studio 2015或者2017(两个都测试过,都是可以的!),之后简称VS
  • windows端的CMake

《Pytorch的C++端(libtorch)在Windows中的使用》

大概流程就是我们使用cmake构建好libtorch工程,然后使用VS打开根据cmake配置好的信息进行编译,所以在进行之后的步骤前一定要提前安装好上述的两样东西。

好了,那么首先我们要配置CmakeList:

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(simnet)

find_package(Torch REQUIRED)
find_package(OpenCV REQUIRED)

if(NOT Torch_FOUND)
    message(FATAL_ERROR "Pytorch Not Found!")
endif(NOT Torch_FOUND)

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(simnet main.cpp)
target_link_libraries(simnet ${TORCH_LIBRARIES} ${OpenCV_LIBS})
set_property(TARGET simnet PROPERTY CXX_STANDARD 11)

和之前的没有什么区别,主要我们需要找到libtorch和opencv库。

接下来使用cmake来进行配置吧,我们首先自己创建一个文件夹,存放我们的主程序main.cpp还有CMakeLists.txt,然后我们再创建一个build的空文件夹,之后我们编译好的文件都存放在build文件夹里头。

目录结构大概就是这样,假设这个文件夹存放在D盘:

  • example
    — build
    — main.cpp
    — CMakeLists.txt

好了,我们打开Window的命令行界面,进入该目录,再进入build文件夹,然后我们设置我们的Cmake参数:

-DCMAKE_PREFIX_PATH=path\to\opencv\build\x64\vc14\lib;path\to\libtorch -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 14 Win64" 

这里需要注意下OpenCV的路径,将上面的位置改成自己的安装位置修改即可,我们需要同时告诉cmake编译工具OpenCV和libtorch的位置信息,然后这里我选择-G"Visual Studio 14 Win64"执行编译器是VS2015的编译工具,如果是2017的话就是-G"Visual Studio 15 Win64这里根据自己的需要进行调整(如果使用VS2017别忘了修改OpenCV中的vc14为vc15)。

编译类型(-DCMAKE_BUILD_TYPE=Release)也要加上,要不然会报错:

Unknown cmake build type:
Call Stack (most recent call first):
  D:/libtorch-gpu/share/cmake/Caffe2/Caffe2Config.cmake:88 (include)
  D:/libtorch-gpu/share/cmake/Torch/TorchConfig.cmake:39 (find_package)
  CMakeLists.txt:4 (find_package)

-- Configuring incomplete, errors occurred!
See also "E:/simnet-gpu/build/CMakeFiles/CMakeOutput.log".
See also "E:/simnet-gpu/build/CMakeFiles/CMakeError.log".

好了,上述具体步骤如下:

C:\Users\dell>D:
D:\>cd example
D:\example>cd build

D:\example\build>cmake -DCMAKE_PREFIX_PATH=D:\opencv4\opencv\build\x64\vc15\lib;D:\libtorch-gpu -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 14 Win64" ..

如果顺利的话应该是Cmake会输出:

-- The C compiler identification is MSVC 19.0.24215.1
-- The CXX compiler identification is MSVC 19.0.24215.1
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE
-- Found CUDA: C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0 (found suitable version "9.0", minimum required is "7.0")
-- Caffe2: CUDA detected: 9.0
-- Caffe2: CUDA nvcc is: C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0/bin/nvcc.exe
-- Caffe2: CUDA toolkit directory: C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0
-- Caffe2: Header version is: 9.0
-- Found cuDNN: v7.0.4  (include: C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0/include, library: C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0/lib/x64/cudnn.lib)
-- Autodetected CUDA architecture(s): 6.1
-- Added CUDA NVCC flags for: -gencode;arch=compute_61,code=sm_61
-- Found torch: D:/libtorch-gpu/lib/torch.lib
-- Pytorch status:
--     libraries: torch;caffe2_library;caffe2_gpu_library;C:/Program Files/NVIDIA Corporation/NvToolsExt/lib/x64/nvToolsExt64_1.lib;C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0/lib/x64/cudart_static.lib
-- Found OpenCV: D:/opencv4/opencv/build (found version "4.0.0")
-- OpenCV library status:
--     version: 4.0.0
--     libraries: opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio;opencv_world
--     include path: D:/opencv4/opencv/build/include
-- Configuring done
-- Generating done
-- Build files have been written to: E:/simnet-gpu/build

这时Cmake会在build文件夹中生成一些列项目信息,可以使用VS打开(打开下面箭头标注的文件)。

如果你的电脑装有两个版本以上的Visual Studio,那么这里要注意如果我们之前使用VS15编译的话那么就要使用VS15去打开这个文件,也就是之前编译使用的工具和之后打开工程的版本应该一致

《Pytorch的C++端(libtorch)在Windows中的使用》

打开后大概是这样子的:

《Pytorch的C++端(libtorch)在Windows中的使用》

这里simnet是我的项目名字,我们将该项目设为启动项(可以看到simnet字体比较粗)从而方便调试。

上述的代码在之前的那篇文章中已经提到过,这里简单展示下main函数部分,在这段代码中,我们利用OpenCV读取摄像头数据转化为Tensor,然后投入模型中进行判断:

...

cv::VideoCapture stream(0);
cv::namedWindow("Gesture Detect", cv::WINDOW_AUTOSIZE);

// 下面的 new-mobilenetv2-128_S-win.pt 是我在Window上利用Pytorch导出的trace后的模型
string model_path = "new-mobilenetv2-128_S-win.pt";
std::shared_ptr<torch::jit::script::Module> module = torch::jit::load(model_path);

...

关于模型

这里还有一点需要注意,使用libtorch导入的模型必须是和libtorch相匹配版本的Pytorch导出的模型,也就是说如果我拿我之前在linux端导出的模型(之前我在linux端导出的模型使用的Pytorch版本不是稳定版),在这里使用window下的libtorch读取是会发生错误的,所以我们需要利用正式版1.0版本的Pytorch去导出一个模型。

这里我直接在window下安装稳定版的Pytorch-1.0(官方已经有稳定版的win版的Pytorch了),然后利用以下代码导出traced后的模型。

# 读入之前训练好的.pth模型
state = torch.load('model/new-mobilenetv2-128_S.pth', map_location=device)
model.load_state_dict(state['model'], strict=True)

# example = torch.rand(1, 3, 128, 128).cuda()
# model.to(device)

# torch_out = torch.onnx.export(model,
#                               example,
#                               "new-mobilenetv2-128_S.onnx",
#                               verbose=True,
#                               export_params=True
#                               )

example = torch.ones(1, 3, 128, 128)

model = model.eval()

traced_script_module = torch.jit.trace(model, example)
output = traced_script_module(example)
print(traced_script_module)
# 导出trace后的模型
traced_script_module.save('new-mobilenetv2-128_S-win.pt')

开始编译

然后,我们直接点击VS中的调试器进行调试即可,这里我选择了Release(与之前cmake一致)进行编译。

《Pytorch的C++端(libtorch)在Windows中的使用》

点击后开始编译,可能会输出一堆警告,这里不用理会:

《Pytorch的C++端(libtorch)在Windows中的使用》

如果顺利的话,直接开始运行:

《Pytorch的C++端(libtorch)在Windows中的使用》

在VS中可以运行后,我们可以找到其单独的.exe文件,然后将必要的.dll文件(CPU和GPU的all不同)和模型与simnet.exe放到一个文件夹中,这时,我们点击simnet.exe就可以直接运行了:

《Pytorch的C++端(libtorch)在Windows中的使用》

后记

libtorch在WIndow端的使用也不是很复杂,我们根据运行环境不同下载不同版本的libtorch(CPU和GPU),然后使用cmake配置后,利用VS进行编译就可以直接使用,其中遇到的问题大部分时环境的问题,我们的代码并不需要修改,是可以跨平台的,我也在VS2015和VS2017中进行了测试,都是可以的。

可能会遇到的问题

我在其中遇到了两个小问题,稍微查下就解决了,现在贴出来,如果和我遇到同样的就不用去google了…

在Window下查看指定camke编译器的命令

在window中指定cmake的编译器构架:

cmake -G
CMake Error: No generator specified for -G

Generators
  Visual Studio 15 2017 [arch] = Generates Visual Studio 2017 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 14 2015 [arch] = Generates Visual Studio 2015 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 12 2013 [arch] = Generates Visual Studio 2013 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 11 2012 [arch] = Generates Visual Studio 2012 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 10 2010 [arch] = Generates Visual Studio 2010 project files.
                                 Optional [arch] can be "Win64" or "IA64".
  Visual Studio 9 2008 [arch]  = Generates Visual Studio 2008 project files.
                                 Optional [arch] can be "Win64" or "IA64".
  Borland Makefiles            = Generates Borland makefiles.
  NMake Makefiles              = Generates NMake makefiles.
  NMake Makefiles JOM          = Generates JOM makefiles.
  Green Hills MULTI            = Generates Green Hills MULTI files
                                 (experimental, work-in-progress).
  MSYS Makefiles               = Generates MSYS makefiles.
  MinGW Makefiles              = Generates a make file for use with
                                 mingw32-make.
  Unix Makefiles               = Generates standard UNIX makefiles.
  Ninja                        = Generates build.ninja files.
  Watcom WMake                 = Generates Watcom WMake makefiles.
  CodeBlocks - MinGW Makefiles = Generates CodeBlocks project files.
  CodeBlocks - NMake Makefiles = Generates CodeBlocks project files.
  CodeBlocks - NMake Makefiles JOM
                               = Generates CodeBlocks project files.
  CodeBlocks - Ninja           = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles  = Generates CodeBlocks project files.
  CodeLite - MinGW Makefiles   = Generates CodeLite project files.
  CodeLite - NMake Makefiles   = Generates CodeLite project files.
  CodeLite - Ninja             = Generates CodeLite project files.
  CodeLite - Unix Makefiles    = Generates CodeLite project files.
  Sublime Text 2 - MinGW Makefiles
                               = Generates Sublime Text 2 project files.
  Sublime Text 2 - NMake Makefiles
                               = Generates Sublime Text 2 project files.
  Sublime Text 2 - Ninja       = Generates Sublime Text 2 project files.
  Sublime Text 2 - Unix Makefiles
                               = Generates Sublime Text 2 project files.
  Kate - MinGW Makefiles       = Generates Kate project files.
  Kate - NMake Makefiles       = Generates Kate project files.
  Kate - Ninja                 = Generates Kate project files.
  Kate - Unix Makefiles        = Generates Kate project files.
  Eclipse CDT4 - NMake Makefiles
                               = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - MinGW Makefiles
                               = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Ninja         = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.

缺失nvToolsExt64_1.dll

如果在使用GPU版本的libtorch的时候遇到缺少nvToolsExt64_1.dll,直接从网上下一个放到C:\Windows\System32目录下即可(win10)。

附带的资源文件:

下方资源文件为上文所述的 new-mobilenetv2-128_S-win.pt 

通过tortch.jit.trace导出,以便大家快速使用,在CPU端和GPU端都进行了测试可以正常工作。

链接:https://pan.baidu.com/s/1bSwzH7YNZnRk3bLq3LMF8Q
提取码:2jjd

  点赞
本篇文章采用 署名-非商业性使用-禁止演绎 4.0 国际 进行许可
转载请务必注明来源: https://oldpan.me/archives/pytorch-windows-libtorch

   关注Oldpan博客微信公众号,你最需要的及时推送给你。


  1. z
    zzz说道:

    博主您好,我用unet训练的模型trace之后,在c++中用libtorch调用,但是输出的图片为全黑色,像素都是0,这种情况如何解决呢?

  2. 下士A说道:

    :redface: 博主我在一台电脑上编的程序移到另一台电脑上,另一台电脑没有libtorch全文件,需要把libtorch下所有的dll都移过去吗?好像有点大的,现在是没有运行成功

  3. Y
    YY说道:

    我跑GPU下的权重时不能正确的输出,也没有错误显示。但是跑CPU下面的权重时,能够正确的执行prediction.
    请问这可能是什么原因?

    1. O
      Oldpan说道:

      不能正确的输出是什么意思,结果和cpu的不一致么?

  4. 小树说道:

    博主你好,libtorch不是官网说已经编译好了的,还是必须经过cmake再编译一遍吗

    1. O
      Oldpan说道:

      有编译好的版本,需要提前弄明白和你的编译环境是否匹配。也可以在自己的环境再编译一遍,pytorch编译的时候会顺便编译得到libtorch

  5. 温同学说道:

    博主你好,我想问一下,为啥用cuda进行模型预测,内存会一下子暴涨,并且停掉之后还是没有降下去。大佬知道怎么释放cuda或者内存吗?

    1. O
      Oldpan说道:

      停掉之后是指程序运行完毕了吗,释放内存我博客中有一篇文章有写

  6. c
    chalson说道:

    博主你好,我是纯cpu的电脑,cmake时出现找不到cuda,我又没法装cuda,怎么办?

    CUDA_TOOLKIT_ROOT_DIR not found or specified
    -- Could NOT find CUDA (missing: CUDA_TOOLKIT_ROOT_DIR CUDA_NVCC_EXECUTABLE CUDA_INCLUDE_DIRS CUDA_CUDART_LIBRARY) (Required is at least version "7.0")

  7. 烟雨说道:

    请问博主可以给出.pth转.pth的完整代码吗?

    1. O
      Oldpan说道:

      .pth转.pth?我没看明白,C++代码我找下

  8. 烟雨说道:

    博主你好,我运行的时候出现错误:错误 LNK1181 无法打开输入文件“torch-NOTFOUND.obj”
    不知道为什么?查了很久都没有找到解决方案。

    1. O
      Oldpan说道:

      唔...这个看不出来呀,Window下确实坑很多,你是按照我的方式来的吗

      1. 烟雨说道:

        是的,我的这些问题解决了,发现libtorch提供的windows版只有debug方式,所以用release方式始终不对,不知道你和好多博主是怎么完成的 :lol:
        对了,博主可以把你的c++代码给我看一下吗?我现在调试的有些懵逼。如果可以的话,可以发我邮箱里,谢谢。

    2. j
      jiaopoint说道:

      我也遇到同样问题了,尴尬

  9. 烟雨说道:

    博主你好,我通过你的方式来在windows上部署,但是我总是在found torch这一步无法完成,找不到torch.lib,

  10. 谢琛说道:

    楼主,我编译好在调试的时候遇到“未加载kernelbase.pdb”,请问你遇到过这个问题吗?我使用的是pytorch1.1, VS2017

  11. 阿国说道:

    博主你好,按照你的教程我跑到最后生成.exe文件之后,打开就一闪而过,请问是因为我的libtorch是gpu版本的,而.pt文件是cpu版本的原因吗

    1. O
      Oldpan说道:

      应该不是,CPU可以打开GPU版本的,一闪而过让我想知道你有没有加类似于pause类的函数

      1. 阿国说道:

        我加了system("pause"),但是仍然一闪而过,尽管只是输出一个ok

        1. O
          Oldpan说道:

          确定加对了么,用getch也可以,或者用opencv库里的wait

          1. 阿国说道:

            加了的,尚未解决。博主我还想请教一下关于libtorch与pytorch的版本匹配问题,我是在ubantu上用pytorch1.1训练的导出的模型,cuda是10.0;然后在windows上libtorch也是1.1,但是显卡不行,不支持cuda10.0就装了9.0,在vs调试的时候就报未经处理的异常: Microsoft C++ 异常: c10::Error,请问这是因为cuda不匹配的原因吗?

            1. O
              Oldpan说道:

              应该不是cuda问题,你应该在win上导出模型在win上导入,用ubuntu上导出win导入会出现符号不匹配的情况

          2. 阿国说道:

            确实遇到了这个 问题。。谢谢你的回复

          3. 阿国说道:

            博主你还,像你说的我先在win下利用ubantu训练好的.pth文件导出.pt文件,然后在win下导入,当我设置好命令行参数,调试运行时,报未经处理的异常: Microsoft C++ 异常: c10::Error:未加载kernelbase.pdb,kernelbase.pdb 包含查找模块 KernelBase.dll 的源文件所需的调试信息,问题出在我加载模型那一行,如下:
            torch::Device available_device(device_type);
            std::cout << "1111111111111" << std::endl;
            //反序列化pytorch模型,并加载到module变量
            std::shared_ptr model = torch::jit::load(modelName,available_device);
            std::cout << "3333333333333" << std::endl;
            请问您知道这是什么问题嘛?