进入PyTorch官网,获取对应的LibTorch链接。根据个人设备配置获取对应的LibTorch下载地址,这里我选择 Stable > Linux > LibTorch > C++/Java CUDA 10.2,获得下载地址:
Download here (Pre-cxx11 ABI): https://download.pytorch.org/libtorch/cu102/libtorch-shared-with-deps-1.11.0%2Bcu102.zip Download here (cxx11 ABI): https://download.pytorch.org/libtorch/cu102/libtorch-cxx11-abi-shared-with-deps-1.11.0%2Bcu102.zip
获得下载地址之后,在安装目录(例如${HOME})下执行
wget https://download.pytorch.org/libtorch/cu102/libtorch-cxx11-abi-shared-with-deps-1.11.0%2Bcu102.zip uzip libtorch-cxx11-abi-shared-with-deps-1.11.0+cu102.zip
(base) cilinyan@amax:~$ cd libtorch (base) cilinyan@amax:~/libtorch$ tree -d -L 1 . ├── bin ├── include # 包含程序需要include的头文件 ├── lib # 包含含链接的共享库 └── share # 包含必要的CMake配置文件使得find_package(Torch) 4 directories2. 官方 demo
Next, let’s write a tiny C++ file called dcgan.cpp that includes torch/torch.h and for now simply prints out a three by three identity matrix:
''' main.cpp ''' #include#include int main() { torch::Tensor tensor = torch::eye(3); std::cout << tensor << std::endl; return 0; }
To build this tiny application as well as our full-fledged training script later on we’ll use this CMakeLists.txt file:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.16) # 指定 CMake 最低版本
project(myTest CXX)
set(CMAKE_CXX_STANDARD 14) # C++11 会报错
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(Torch_DIR /data2/cilinyan/libtorch/share/cmake/Torch) # 指定 LibTorch 路径
find_package(Torch REQUIRED) # 指示 CMake 查找 LibTorch 库的构建配置
add_executable(myTest main.cpp)
target_link_libraries(myTest "${TORCH_LIBRARIES}")
set_property(TARGET myTest PROPERTY CXX_STANDARD 14)
简单的编译运行一下:
(base) cilinyan@amax:~/clyan/xshell$ tree
.
├── CMakeLists.txt
└── main.cpp
0 directories, 2 files
(base) cilinyan@amax:~/clyan/xshell$ cmake .
-- The CXX compiler identification is GNU 8.4.0
-- Check for working CXX compiler: /usr/bin/c++
...
-- Found Torch: /data2/cilinyan/libtorch/lib/libtorch.so
-- Configuring done
-- Generating done
-- Build files have been written to: /data2/cilinyan/clyan/xshell
(base) cilinyan@amax:~/clyan/xshell$ make
Scanning dependencies of target myTest
[ 50%] Building CXX object CMakeFiles/myTest.dir/main.cpp.o
[100%] Linking CXX executable myTest
[100%] Built target myTest
(base) cilinyan@amax:~/clyan/xshell$ tree -L 1
.
├── CMakeCache.txt
├── CMakeFiles
├── cmake_install.cmake
├── CMakeLists.txt
├── detect_cuda_compute_capabilities.cu
├── detect_cuda_version.cc
├── main.cpp
├── Makefile
└── myTest
1 directory, 8 files
(base) cilinyan@amax:~/clyan/xshell$ ./myTest
1 0 0
0 1 0
0 0 1
[ CPUFloatType{3,3} ]
3. 模块 API 基础
与 Python 接口一致,基于 C++ 前端的神经网络由称为模块的可重用构建块组成。有一个基本模块类,所有其他模块都从该类派生。在 Python 中,这个类是 torch.nn.Module,而在 C++ 中,它是torch::nn::Module. 除了 forward()实现模块封装的算法的方法外,模块通常包含三种子对象中的任何一种:参数、缓冲区和子模块。
参数和缓冲区以张量的形式存储状态。参数记录梯度,而缓冲区不记录。参数通常是神经网络的可训练权重。缓冲区的示例包括用于批量标准化的均值和方差。为了重用特定的逻辑和状态块,PyTorch API 允许嵌套模块。嵌套模块称为 子模块。
Parameters, buffers and submodules must be explicitly registered. Once registered, methods like parameters() or buffers() can be used to retrieve a container of all parameters in the entire (nested) module hierarchy.类似地,类似的方法to(...),例如to(torch::kCUDA)将所有参数和缓冲区从 CPU 移动到 CUDA 内存,适用于整个模块层次结构。
4. 模型部署Python 模型保存以及测试
import torch
import torch.nn as nn
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc = nn.Linear(in_features=5, out_features=3)
def forward(self, x):
return self.fc(x)
if __name__ == '__main__':
torch.manual_seed(5)
x = torch.tensor([[-9., 2., 3., 4., 5.], [2., 3., 4., 5., 6.]])
model = Net()
y = model(x)
cls = torch.argmax(y, dim=1)
scripted_module = torch.jit.script(model.eval())
scripted_module.save("model.pt")
print(y)
print(cls)
输出:
tensor([[ 0.8604, 4.0944, -0.2227],
[ 4.8016, 0.2598, 0.8346]], grad_fn=)
tensor([1, 0])
C++ 模型部署及测试
#include#include #include using namespace std; int main() { // torch::Device device(torch::cuda::is_available() ? torch::kCUDA : torch::kCPU); float nums[2][5] = {{-9, 2, 3, 4, 5}, {2, 3, 4, 5, 6}}; torch::Tensor x = torch::from_blob(nums, {2, 5}, dtype(torch::kFloat)); auto model = torch::jit::load("model.pt"); torch::Tensor y = model.forward({x}).toTensor(); auto cls = torch::argmax(y, 1); cout << "x :" << endl << x << endl; cout << "y :" << endl << y << endl; cout << "cls:" << endl << cls << endl; return 0; }
输出:
x :
-9 2 3 4 5
2 3 4 5 6
[ CPUFloatType{2,5} ]
y :
0.8604 4.0944 -0.2227
4.8016 0.2598 0.8346
[ CPUFloatType{2,3} ]
cls:
1
0
[ CPULongType{2} ]



