torch::jit::load()是libtorch唯一支持的模型加载方式,仅接受torchscript格式(.pt),不支持state_dict(.pth);加载后需显式指定设备、校验输入张量shape/dtype/contiguous性,并为多线程推理创建独立module实例。

torch::jit::load() 是唯一可用的加载入口
LibTorch 不支持 torch::load() 或直接反序列化 state_dict,它只认 TorchScript 格式(即通过 torch.jit.trace 或 torch.jit.script 导出的 .pt 文件)。如果你拿的是纯权重文件(比如 model.pth 里只有 state_dict),torch::jit::load() 会直接报错:「Expected object of type ScriptModule but found type dict」。
常见错误现象:
-
torch::jit::load("model.pth")报Expected value of type ScriptModule - 用 Python 的
torch.save(model.state_dict(), ...)保存的文件,在 C++ 里无法被识别
必须确认你的 .pt 文件是 TorchScript 格式。最简单的验证方式是在 Python 中跑:
import torch
m = torch.jit.load("model.pt")
print(type(m)) # 应该输出 <class></class>
加载时必须显式指定设备,且不能依赖默认行为
LibTorch 不会自动把模型放到 GPU 上——哪怕你链接的是 CUDA 版本的库,torch::jit::load() 默认仍在 CPU 上加载。如果模型里有 CUDA 张量或算子,但没做设备适配,运行 forward() 时会崩溃,报类似 CUDA error: invalid device ordinal 或 Expected all tensors to be on the same device。
正确做法是加载后立即调用 .to():
-
auto module = torch::jit::load("model.pt"); module.to(torch::kCUDA);(需确保 CUDA 可用) - 更稳妥的是在加载时就指定设备:
torch::jit::load("model.pt", torch::kCUDA); - 若部署环境不确定是否含 GPU,建议统一先 load 到 CPU,再按需
.to(),避免初始化失败
注意:torch::kCUDA 不等价于 torch::Device(torch::kCUDA, 0);后者可指定卡号,前者默认使用当前主卡(device 0),多卡场景下务必显式传入设备 ID。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
输入张量 shape 和 dtype 必须与 traced 时完全一致
TorchScript 模型在 trace 阶段固化了输入签名,包括维度数量、大小(除 batch 维外)、数据类型和内存布局(如 NCHW)。C++ 中构造的输入张量若不匹配,会触发运行时报错,例如:
-
Expected input to have 4 dimensions, but got 3(忘了加 batch 维) -
Expected object of scalar type Float but got scalar type Byte(图像没转float,或没除以 255) -
Input tensor is not contiguous(OpenCV 读图后未调.contiguous())
典型预处理链(以 ResNet 类图像模型为例):
cv::Mat img = cv::imread(path);
cv::cvtColor(img, img, cv::COLOR_BGR2RGB);
cv::resize(img, img, cv::Size(224, 224));
img.convertTo(img, CV_32FC3, 1.0 / 255.0); // 注意是 float,不是 double
auto tensor = torch::from_blob(img.data, {1, 224, 224, 3}, torch::kFloat).permute({0, 3, 1, 2}).contiguous();
关键点:.permute() 调整通道顺序,.contiguous() 确保内存连续,缺一不可。
多线程推理必须为每个线程创建独立 Module 实例
torch::jit::script::Module 对象**不是线程安全的**。多个线程共用一个 module 实例并发调用 .forward(),极大概率导致 segfault 或结果错乱,尤其在启用 cuDNN 或 autograd 时。
正确做法:
- 不要全局单例
Module;每个线程持有一个自己的副本 - 若担心内存开销,可共享底层权重(通过
module.copy()或从同一文件重复load()),但绝不能复用同一个对象 - 在 thread-local storage 或 worker 初始化阶段完成
torch::jit::load(),而非在每次推理前重复加载
容易被忽略的一点:即使你只做 inference,也应在加载后调用 module.eval() 和 torch::NoGradGuard no_grad;,否则某些算子(如 Dropout)仍可能激活,影响结果一致性。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










