碎碎念
需要把Python解释器嵌入C++程序中使用,并且同时想要能够同时在C++代码和Python代码中使用Torch(所以不能仅使用libTorch),能通过pybind11在python和C++代码中传递tensor(at::Tensor和torch.Tensor)。最开始尝试将使用pip安装的cuda版pytorch下的torch/lib中的.so文件作为动态库参与链接,却发生了ABI不兼容的问题,查询一波资料后发现只能自行编译pytorch解决。
折腾了很长时间才成功,这里面坑太过于多,遂记之。
环境
- 系统:ArchLinux x64
- Nvidia-docker
- 正确安装的nvidia驱动
- 科学上网
下载PyTorch源码
必须使用git clone,否则会在build的时候因为git命令的执行出错而无法build。需要科学上网,否则大概率无法完成所有子模块的同步
git clone -b v1.13.1 --recursive https://github.com/pytorch/pytorch
等待确保完成
拉取Docker镜像
我首先在ArchLinux上编译,总是遇到莫名其妙的错误,于是用了pytorch docker镜像的ubuntu系统,首先运行下面的命令,注意将-v 参数后面的/home/hfcloud/Program/pytorch替换为你刚才clone下来的pytorch的路径
sudo nvidia-docker pull pytorch/pytorch:latest
sudo nvidia-docker run --name=buildtorch -v /home/hfcloud/Program/pytorch:/workspace/pytorch -td pytorch/pytorch
sudo nvidia-docker exec -it buildtorch /bin/bash
能够进入容器内的ubuntu系统这一步就算成功,进去后先运行一下
conda init
再退出来,这样里面的codna也就可以使用了
配置环境
安装系统工具
apt-get update
apt-get install vim git build-essential libxml2 libomp-dev
(可能没记全,缺啥看着再装)
创建专用于构建PyTorch的虚拟环境
创建虚拟环境,python的版本要能够满足pytorch的需要。如果像我一样需要把python解释器嵌入到C++程序中使用,那么虚拟环境中的python版本号的前两部分必须和你的C++程序链接的python的版本号相同(第三部分可以不同,ABI兼容的)
conda create -n BuildTorch python==3.10
conda activate BuildTorch
cd pytorch
conda install astunparse numpy ninja pyyaml mkl mkl-include setuptools cmake cffi typing_extensions future six requests dataclasses
pip install -r requirements.txt
安装cuda toolkit
这里的坑不小。容器里的ubuntu的apt源提供的cuda toolkit版本不太行,编译的时候大概编译到第6000多个.o文件的时候会报错提示找不到cuSolver中的某一个函数的定义。所以我们自己装cuda toolkit 11.6
wget https://developer.download.nvidia.com/compute/cuda/11.6.2/local_installers/cuda_11.6.2_510.47.03_linux.run
chmod +x cuda_11.6.2_510.47.03_linux.run
./cuda_11.6.2_510.47.03_linux.run
运行安装程序的时候最开始会卡主一会儿,稍等一下就可以,然后就进入了安装界面,选择组件的时候只要cuda toolkit就可以,其他的都不需要。
装好后在/usr/local下面就有cuda-11.6文件夹,把它软连接到/opt/cuda
ln -s /usr/local/cuda-11.6 /opt/cuda
构建!
需要先设置一些环境变量,其他的环境变量也可以参考pytorch github页面上的说明,这是我用的配置:
export CUDA_NVCC_EXECUTABLE=/opt/cuda/bin/nvcc
export CUDA_HOME=/opt/cuda
export CUDDN_INCLUDE_PATH=/opt/cuda/include
export CUDNN_INCLUDE_PATH=/opt/cuda/include
export CUDNN_LIBRARY_PATH=/opt/cuda/lib64
export _GLIBCXX_USE_CXX11_ABI=1
export TORCH_CUDA_ARCH_LIST="7.5 8.0 8.6"
export USE_CUDA=1
export USE_CUDNN=1
export USE_MKLDNN=1
git config --global --add safe.directory /workspace/pytorch
export CMAKE_PREFIX_PATH=${CONDA_PREFIX:-"$(dirname $(which conda))/../"}
export PATH=/opt/cuda/bin:$PATH
python setup.py build
接下来等(很长)一段时间,就构建成功了.
拷贝头文件和库文件
基于pytorch的C++开发需要头文件和库文件可以从镜像里捞出来:
头文件从pytorch/torch/include里面拿
库文件包括:
pytorch/torch/lib下的所有.so文件(软链接可以不要)
/opt/conda/lib/下的:
libmkl_core.so.1
libmkl_gnu_thread.so.1
libmkl_intel_lp64.so.1
libmkl_avx2.so.1
libmkl_def.so.1
我猜如果不用MKLDNN的话,可能就不需要这么多mkl系列的库了
/opt/cuda/lib64里面拿
libcublas.so.11
libcublasLt.so.11
libcudart.so.11.0
libcufft.so.10
libcusparse.so.11
/opt/cuda/extras/CUPTI/lib64里面拿
libcupti.so.11.6
如果后续发现有什么缺的库继续回来捞就行了=。=
为了方便以后有需要的时候再次使用这个配好编译pytorch环境的镜像,可以docker commit存一下当前的容器~