简介:工作需要,需要使用C++来使用Pytorch,学无止境呀!
入门
在两眼一眼的情况下先问Kimi:首先,使用Pytorch进行模型训练最优的方式还是使用Python接口,简单易用,那么什么情况下需要用Pytorch的C++接口呢?—— 往往就是在模型部署推理阶段。其次,就看怎么实现模型C++部署:
- 先将Python环境中训练好的模型文件导出为TorchScript格式,其实就是“xxx.pt”文件;
- 安装LibTorch(PyTorch的C++分发版),使用C++版本的API函数加载模型文件和编写计算代码;
- 写CMakeLists.txt使用CMake来进行编译管理;
初次尝试
- 下载安装LibTorch ```bash wget https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-2.3.1%2Bcpu.zip
unzip libtorch-cxx11-abi-shared-with-deps-2.3.1%2Bcpu.zip
2. 编写一个简单的C++代码测试LibTorch
```C++
// example-app.cpp
#include <torch/torch.h>
#include <iostream>
int main() {
torch::Tensor tensor = torch::rand({2, 3});
std::cout << tensor << std::endl;
}
- 编写一个CMakeLists.txt ```CMake cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(example-app)
设置C++17标准
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)
查找Torch包
find_package(Torch REQUIRED)
添加可执行文件
add_executable(example-app example-app.cpp)
链接Torch库
target_link_libraries(example-app “${TORCH_LIBRARIES}”)
确保C++17标准被正确传递
if(CMAKE_CXX_COMPILER_ID STREQUAL “GNU”) target_compile_options(example-app PRIVATE “-Wall” “-Wextra”) elseif(CMAKE_CXX_COMPILER_ID STREQUAL “Clang”) target_compile_options(example-app PRIVATE “-stdlib=libc++”) endif()
确保C++17标准被正确传递
set_target_properties(example-app PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON )
4. 编译运行
```bash
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=./libtorch ..
# 编译
make
# 运行
./example-app
另外,如果已经安装了Pytorch的Python库,那么不下载LibTorch也是可以编译运行的:
cmake -DCMAKE_PREFIX_PATH=`python3 -c 'import torch;print(torch.utils.cmake_prefix_path)'` ..
后知后觉,发现Pytorch官方LibTorch下载使用文档。
在ARM 64位(aarch64)设备上编译libtorch
在自己电脑跑通,但在需要运行的国产机上报错:
Scanning dependencies of target example-app
[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o
[100%] Linking CXX executable example-app
/usr/bin/ld: ../libtorch/lib/libtorch.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/example-app.dir/build.make:88:example-app] 错误 1
make[1]: *** [CMakeFiles/Makefile2:76:CMakeFiles/example-app.dir/all] 错误 2
make: *** [Makefile:84:all] 错误 2
使用uname -m
才发现是ARM 64位(aarch64)的设备,看网上说需要源码编译。
先下载源码:
git clone https://github.com/pytorch/pytorch --recursive && cd pytorch
git checkout v1.2.0
git submodule sync
git submodule update --init --recursive
上面四条命令依次解释如下:
- –recursive选项确保了同时克隆了所有子模块(submodules),这些子模块是PyTorch项目依赖的其他Git仓库。
- 这条命令切换到PyTorch的v1.2.0版本。
- 这条命令用于与远程仓库同步子模块的引用。这确保了子模块的引用与远程仓库中的当前状态一致。
- 这条命令用于初始化和更新所有子模块。–init选项用于创建所有尚未克隆的子模块,–recursive选项用于递归地更新所有子模块。
简单设置:
export USE_CUDA=False
export BUILD_TEST=False
将USE_CUDA设置为False意味着在编译或运行程序时,将不会使用CUDA,也就是说,程序将不会利用GPU进行加速。设置BUILD_TEST为False时,编译系统可能会跳过构建测试代码的步骤,这可以加快编译过程,特别是在不需要测试代码的情况下。
编译:
mkdir build && cd build
python3 ../tools/build_libtorch.py
编译完成之后,整理成libtorch:
# libtorch/
mkdir include
cp -r /home/kylin/zw/pytorch/torch/ ./include
cp -r /home/kylin/zw/pytorch/caffe2/ ./include
cp -r /home/kylin/zw/pytorch/c10/ ./include
cp -r /home/kylin/zw/pytorch/aten/src/ATen/ ./include
cp -r /home/kylin/zw/pytorch/aten/src/TH/ ./include
cp -r /home/kylin/zw/pytorch/aten/src/THCUNN/ ./include
cp -r /home/kylin/zw/pytorch/aten/src/THNN/ ./include
cp -r /home/kylin/zw/pytorch/build/build/lib ./
mkdir share
cp -r /home/kylin/zw/pytorch/torch/share/cmake ./share
文件结构:
├── include
│ ├── ATen
│ ├── c10
│ ├── caffe2
│ ├── TH
│ ├── THCUNN
│ ├── THNN
│ └── torch
├── lib
└── share
└── cmake
折腾了一番之后还是报错:
kylin@kylin-190:~/zw/CppTorch/build$ make
Scanning dependencies of target example-app
[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o
In file included from /home/kylin/zw/LibTorch/include/torch/csrc/WindowsTorchApiMacro.h:3,
from /home/kylin/zw/LibTorch/include/torch/csrc/api/include/torch/cuda.h:3,
from /home/kylin/zw/LibTorch/include/torch/csrc/api/include/torch/all.h:3,
from /home/kylin/zw/LibTorch/include/torch/csrc/api/include/torch/torch.h:3,
from /home/kylin/zw/CppTorch/example-app.cpp:1:
/home/kylin/zw/LibTorch/include/c10/macros/Export.h:44:10: fatal error: c10/macros/cmake_macros.h: 没有那个文件或目录
44 | #include "c10/macros/cmake_macros.h"
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/example-app.dir/build.make:63:CMakeFiles/example-app.dir/example-app.cpp.o] 错误 1
make[1]: *** [CMakeFiles/Makefile2:76:CMakeFiles/example-app.dir/all] 错误 2
make: *** [Makefile:84:all] 错误 2