Pytorch通过LIBTORCH实现C++部署

C++部署模型

在人工智能领域,Python受到学术界的追捧,模型训练比模型部署性能更加重要。然而在实际终端部署方面,低延迟、可移植性和可适用性的需求使得Python成为一个比较差的语言。相反,C++凭借其可移植性、可适用性以及运算速度快等优势,更适合终端部署网络模型。下面我将以我做的部署ReID模型为例子,简要介绍如何利用Libtorch(or: Pytorch for C++ API)实现C++部署Pytorch训练的模型。

环境搭建

  • VS2019
  • OpenCV
    • 4.5.5 + release
  • Libtorch
    • 1.8.1 + release +cpu
  • Cmake

为了使得推理速度更快,OpenCV和Libtorch都推荐使用release版本。下面是几点环境搭建的注意点,很重要!!!

  1. Pytorch和Litorch的版本最好一致
    • 否则就会出现模型加载不了的问题
  2. OpenCV release版本链接库是不带d
    • 比如我的是,release版本的库文件名为:opencv_world455.lib,debug版本的库文件名为:opencv_world455d.lib
  3. CUDA版本也要和Pytorch一致
    • 我电脑没有独显,就直接用的cpu版本的libtorch

部署步骤

Libtorch部署Pytorch模型主要包括以下流程:

  1. Python端导出模型
  2. C++端加载模型
    3.C++执行Script

Python端导出模型

Pytorch训练保存得到的pt模型(pt, pth, pkl只是文件名不同,无本质区别)和C++端加载的pt模型不是同一个东西!实现模型由Python向C++转换,需要依赖torchscript,其保存的后缀名常常简化为.pt.torchscript.pt)。torchscript能够被torchscript编译器推理、编译以及序列化。要想实现Pytorch模型转换为torchscript,有tracingannotation两种方式。下面将将简要介绍tracing方式。

tracing

就是向pytorch模型注入一个简单输入,使用torch.jit.trace对这个流进行跟踪,从而得到torchscript模型。下面是我写的转换pytorch模型的一个例子。

import torch
import torchvision

model = net(class_num=751)
device = torch.device('cpu')
model.load_state_dict(toch.load('best.pt', map_location=device))

x=Variable(torch.FloatTensor(8, 3, 256, 128))
traced_script_model = torch.jit.trace(model, x)
traces_script_model.save('best.torchscript.pt')

torch.jit.trace对这个流进行跟踪, 使用 .save方法序列化模型,以便不依赖python。
注意:

  • 输入要和网络输入大小一致
  • pytorch加载模型的方式要和其保存模型相搭配

C++端加载模型

CMake构建Libtorch工程

先用CMake构建好Libtorch工程。项目文件的组织形式如下:

  • reid
    • include
    • src
    • bin
    • weights
    • data
    • CMakeLists.txt
      下面是CMakeLists文本文件的内容:
cmake_minimum_required (VERSION 3.12)
project (reid_demo_libtorch)

set (TORCH_DIR "E:\\libtorch1.8.1\\libtorch\\share\\cmake\\Torch")
set (OpenCV_DIR "E:\\opencv\\opencv\\build")
find_package (Torch REQUIRED)
find_package (OpenCV REQUIRED)

if (NOT Torch_FOUND)
	message (FATAL_ERROR "Libtorch Not Found!")
endif (NOT Torch_FOUND)
if (NOT OpenCV_FOUND)
	message (FATAL_ERROR "OPenCV Not Found!")
endif (NOT OpenCV_FOUND)

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

aux_source_directory (src SRC_LIST)
include_directories (include)

add_executable (main ${SRC_LIST}) 
target_link_libraries (
	main
	${OpenCV_LIBS}
	${TORCH_LIBRARIES}
)

上面文件的内容主要是找到OpenCV和Libtorch库的位置,输出相关信息,再绑定库。具体的CMake语法可以参考CMake - Linux基础教程

  1. cd reid
  2. mkdir build 建立一个空白的build目录,
    • CMake构建的项目工程会存放到build目录下
  3. cd build
  4. cmake ..
    cmake -DCMAKE_PREFIX_PATH=E:\opencv\opencv\build\x64\vc15\lib;E:\libtorch1.8.1\libtorch -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 16 2019" ..
    • 上面的位置信息根据自己的做相应更改
    • G "Visual Studio 16 2019"是vs2019的编译工具
    • 加上编译类型,Release
C++加载模型

加载序列化的torchscript模型的流程如下:

std::string model_path = "../weights/best.torchscript.pt";
torch::jit::script::Module model;
try {
	model = torch::jit::load(model_path);
}
catch (const c10::Error& error) {
	std::cerr << "error loading model!" << std::endl;
	std::exit(EXIT_FAILURE);
}
model.to(torch::kCPU);
model.eval();

torch::jit::load加载torchscript模型,并对模型反序列化,返回torch::jit::script::Module模型对象。

C++执行Script

下面将介绍C++读取输入数据,利用模型做前向推理的过程。

std::vector<torch::jit::IValue> inputs;
auto input = PreProcessReID(img);
inputs.emplace_back(input);

torch::Tensor outputs = model.forward(inputs).toTensor();
torch::Tensor feature = outputs.contiguous().view({1, -1});
### 部署PyTorch DeepLabV3+模型至C++ #### 准备工作 为了成功部署PyTorch训练好的DeepLabV3+模型到C++环境中,需先安装必要的依赖库并准备环境。确保已安装最新版本的PyTorch C++前端(LibTorch),这允许开发者利用C++调用由Python编写的神经网络模型。 #### 转换模型为 TorchScript 格式 将现有的PyTorch模型转换成可以在C++中加载的形式——即TorchScript格式。此过程通常涉及追踪或脚本化现有模型: ```cpp // 假设model是一个已经实例化的torch::nn::Module对象 torch::jit::script::Module module; module = torch::jit::trace(model, example_input); ``` 这段代码通过给定输入`example_input`来跟踪模型执行路径,并保存该行为作为独立于原始定义的新文件[^1]。 #### 编写C++程序读取和运行模型 创建一个新的C++工程,在其中引入libtorch头文件以及链接相应静态库。编写如下所示的核心逻辑用于初始化、载入预处理过的图像数据并通过模型预测类别标签: ```cpp #include <torch/script.h> #include <iostream> int main() { try { // 加载序列化的.pt模型文件 auto module = torch::jit::load("deeplabv3plus_traced_model.pt"); // 创建随机张量模拟输入图片尺寸 (batch_size=1, channels=3, height=H, width=W) const int H = 256, W = 256; at::Tensor input_tensor = torch::rand({1, 3, H, W}); // 执行推理操作获得输出特征图谱 std::vector<torch::jit::IValue> inputs; inputs.push_back(input_tensor); at::Tensor output_tensor = module.forward(inputs).toTensor(); // 对结果做进一步处理... } catch(const c10::Error& e){ std::cerr << "error loading the model\n"; return -1; } } ``` 上述例子展示了基本框架结构;实际应用时还需考虑更多细节如错误检测与恢复机制等。 #### 性能优化建议 - **量化**:采用INT8精度代替FP32可以显著减少内存占用同时加快计算速度。 - **多线程支持**:启用OpenMP或其他形式的并发控制以充分利用现代CPU架构优势。 - **GPU加速**:如果目标平台具备NVIDIA GPU,则应尽可能迁移运算任务至此硬件上完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值