利用C++调用PyTorch的模型

背景

  1. PyTorch的主要接口是Python语言。虽然Python是许多需要动态和易于迭代的场景的首选语言,但同样有很多情况下,Python的这些属性恰好是不利的。在生产环境中,需要保证低延迟和其它严格的要求,而对于生产场景,C++通常是首选语言,通常C++会被绑定到Java或Go当中;
  2. 第一种方法是在PyTorch中直接使用C++编写PyTorch的前端,而不是通常情况下使用Python来编写PyTorch的前端,实现模型定义、训练和评估以及模型的部署;
  3. 第二种方法是使用Python编写PyTorch的前端,并且实现上述功能;
  4. 众所周知,Python相对于C++在不考虑执行效率的情况下具有很多优势,本文不会讨论这方面的问题。因此,如果可以使用Python编写前端,实现模型定义、训练和评估,而将模型的部署交由C++实现,则可以最大化目标,最快地获得模型以及部署高效的模型。
  5. 概念转换成具体的方案,将Python在PyTorch下训练得到的模型文件转化成C++可以加载和执行的模型文件,并且自此以后不再依赖于Python;
  6. PyTorch模型从Python到C ++之旅由Torch Script实现,Torch Script是PyTorch模型的一种表示,并且可以由Torch Script的编译器理解、编译和序列化。

环境

  1. 安装PyTorch的版本为1.0及以上;
  2. 安装C++版本的LibTorch,LibTorch发行版包含一组共享库,头文件和CMake构建配置文件;
  3. 安装Intel所提供的MKL-DNN库,Caffe依赖此库,编译得到的可执行程序会依赖其中的libmklmllibiomp5动态链接库,若无此库在执行程序时会有错误产生,安装后将这两个动态链接库拷贝至LibTorch的lib目录下;

Mac OS 报错信息如下:
dyld: Library not loaded: @rpath/libmklml.dylib> dyld: Library not loaded: @rpath/libmklml.dylib
Referenced from: ******
Reason: image not found

  1. 安装CMake。

将PyTorch模型转化为Torch Script的两种方法

  1. 如果需要C++使用PyTorch的模型,就必须先将PyTorch模型转化为Torch Script;
  2. 目前有两种方法,可以将PyTorch模型转化为Torch Script:
    • 第一种方法是tracing。该方法通过将样本输入到模型中,并对该过程进行推断从而捕获模型的结构,并记录该样本在模型中的控制流。该方法适用于模型中较少使用控制流的模型;
    • 第二种方法是向模型中添加显式的注释,使得Torch Script编译器可以直接解析和编译模型的代码,受Torch Script强加的约束。该方法适用于使用特定控制流的模型,。

利用Tracing将模型转换为Torch Script

通过tracing的方法将PyTorch的模型转换为Torch Script,则必须将模型的实例以及样本输入传递给torch.jit.trace方法。这样会生成一个torch.jit.ScriptModule对象,模型中的forward方法中用预先嵌入了模型推断的跟踪机制:

import torch
import torchvision

# An instance of your model.
model = torchvision.models.resnet18()

# model.eval()

# An example input you would normally provide to your model's forward() method.
example = torch.rand(1, 3, 224, 224)

# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
traced_script_module = torch.jit.trace(model, example)

# ScriptModule
output = traced_script_module(torch.ones(1, 3, 224, 224))

利用注释将模型转换为Torch Script

  1. 在某些情况下,如模型采用特定形式的控制流(if...else...),可以使用注释的方法将模型转化为Torch Script;
  2. 此模块的forward方法使用依赖于输入的控制流,因此它不适合利用tracing的方法生成Torch Script。可以通过继承torch.jit.ScriptModule并将@torch.jit.script_method标注添加到模型的forward中的方法,来将模型转换为ScriptModule
import torch

class MyModule(torch.nn.Module):
    def __init__(self, N, M):
        super(MyModule, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))

    def forward(self, input):
        if input.sum() > 0:
          output = self.weight.mv(input)
        else:
          output = self.weight + input
        return output
import torch

class MyModule(torch.jit.ScriptModule):
    def __init__(self, N, M):
        super(MyModule, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))

    @torch.jit.script
<think>好的,用户想在C++调用PyTorch模型。我需要分步骤解释,确保结构清晰。首先,我应该想到PyTorch提供了TorchScript来导出模型,这是关键步骤。然后,用户需要配置LibTorch库,这是C++版本的PyTorch。接下来是编写C++代码加载和运行模型。可能还需要注意模型导出的正确性,以及编译时的依赖项和路径设置。用户可能对某些步骤不熟悉,比如如何正确使用TorchScript转换模型,或者如何设置CMakeLists.txt。需要详细说明每个步骤,并提醒常见的陷阱,比如输入张量的格式要与Python端一致。另外,编译命令和必要的库链接也要明确给出,避免用户遇到链接错误。最后,测试示例是否有用,确保用户能验证整个流程是否成功。可能还要提到不同平台的环境配置差异,比如Windows和Linux下的路径问题。总之,要覆盖从模型导出、环境配置、代码编写到编译运行的整个流程,确保用户能逐步跟随操作。</think>在C++调用PyTorch模型可以通过以下步骤实现: --- ### 一、前置准备 1. **安装LibTorch** - 从PyTorch官网下载对应C++库:https://pytorch.org/get-started/locally/ - 选择与Python端PyTorch版本匹配的LibTorch版本 2. **导出PyTorch模型为TorchScript格式** ```python # Python端代码示例 import torch import torchvision # 创建/加载模型 model = torchvision.models.resnet18(pretrained=True) model.eval() # 转换为TorchScript example_input = torch.rand(1, 3, 224, 224) traced_script_module = torch.jit.trace(model, example_input) traced_script_module.save("model.pt") # 保存模型文件 ``` --- ### 二、C++项目配置 1. **CMakeLists.txt配置示例** ```cmake cmake_minimum_required(VERSION 3.0) project(torch_inference) set(CMAKE_PREFIX_PATH "/path/to/libtorch") # 修改为你的LibTorch路径 find_package(Torch REQUIRED) add_executable(main main.cpp) target_link_libraries(main "${TORCH_LIBRARIES}") set_property(TARGET main PROPERTY CXX_STANDARD 14) ``` --- ### 三、C++代码实现 ```cpp #include <torch/script.h> #include <iostream> int main() { // 1. 加载模型 torch::jit::script::Module module; try { module = torch::jit::load("model.pt"); } catch (const c10::Error& e) { std::cerr << "模型加载失败: " << e.what() << std::endl; return -1; } // 2. 准备输入张量 std::vector<torch::jit::IValue> inputs; inputs.push_back(torch::ones({1, 3, 224, 224})); # 输入尺寸需与模型匹配 // 3. 执行推理 at::Tensor output = module.forward(inputs).toTensor(); // 4. 处理输出 std::cout << "输出结果:\n" << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << std::endl; return 0; } ``` --- ### 四、编译与运行 1. **编译命令** ```bash mkdir build cd build cmake .. make -j4 ``` 2. **运行程序** ```bash ./main ``` --- ### 五、注意事项 1. **输入输出一致性** - C++端的输入张量维度、数据类型必须与Python训练时一致 - 建议在Python端添加输入预处理代码 2. **GPU支持** 如需使用GPU: ```cpp module.to(torch::kCUDA); inputs.push_back(torch::ones({1,3,224,224}).to(torch::kCUDA)); ``` 3. **异常处理** - 建议使用try-catch块处理加载/推理异常 - 注意内存管理,避免内存泄漏 --- ### 六、验证测试 建议先用Python生成测试输入,在C++端验证输出是否一致,确保模型转换正确性。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值