Pytorch源码编译简明指南

2023-10-19 10:48:06 浏览数 (1)

前言

最近在浅尝Pytorch的源码,利用业余时间去品读品读,看着看着,第一次对Pytorch有了重新的认识。

原来现在Pytorch的版图是如此之大,Pytorch已经不是一年前的Pytorch了。

在集成了Caffe2之后,Pytorch已经开始变成了庞然大物,涉及到的东西也远远不是之前的caffe可以比较了,总之,Pytorch有很多很多值得我们学习的地方,这篇文章简单讲讲编译Pytorch的一些额外知识,让我们自己亲手编译Pytorch的时候不是盲目去编译,而是有目的有选择的来。

之前所写的相关文章,也可以作为参考:

  • Pytorch-0.4.1-cuda9.1-linux源码安装指南
  • 深度学习-在ubuntu16.04安装CUDA9.1-总结(问题完全解决方案)
  • pytorch-0.2成功调用GPU:ubuntu16.04,Nvidia驱动安装以及最新cuda9.0与cudnnV7.0配置

Pytorch的生态:

其中有Pytorch自家的库也有一块合作的,可以看出FaceBook的野心挺大,但对于我们来说究竟是好是坏呢,总之希望FB抽出更多人力好好打磨Pytorch吧。

获取源代码

编译首先是要获取源代码。

官方获取源代码是最好的方式,从Pytorch的github官网可以下载最新的代码。

记住,从官方克隆最新的代码的时候要加入recursive这个参数,因为Pytorch本身需要很多的第三方库参与编译:

代码语言:javascript复制
git clone --recursive https://github.com/pytorch/pytorch

当然也可以从release界面却下载之前的稳定版本源代码。如果我们是直接下载官方提供的源码包或者正式的release包,那么我们需要在下载之后执行

代码语言:javascript复制
git submodule update --init --recursive

上面这条命令是下载并更新第三方库,我们要保证需要的第三方库都下载完毕,不然在编译过程中会中断。

目录结构

以下是Pytorch源码包展开的目录结构(只展示了主要的一些文件夹),其中主要的源码都在以下展示的文件夹中:

其中使用红箭头标注的就是几个比较重要的核心库。下面简单介绍一下:

核心文件夹

核心文件夹主要是c10、aten、torch、caffe2.

为什么将c10放到最前面呢?

因为官方已经表明c10目录是最重要的源代码文件夹,也就是几乎所有的源代码都与这里的代码有关系,比如我们的类型定义,Pytorch最重要的Tensor的内存分配方式等等,都在这个文件夹中,官方也说到了,之后会慢慢将Aten中的代码移至这个文件夹,也就是说这个文件夹将包含Pytorch中最核心的代码。

Aten文件夹则包含了一些实现了Tensor的底层(和c10类似),也包括了很多的层前向代码和后向实现的代码(例如卷积层的前向和后向操作代码),包括CPU和GPU端,总之都是C 的核心操作代码。

torch文件夹也同样重要,其中主要包含了一些稍微高层些的操作函数,例如torch.ones等,有C 和Python端,也包括了Python核心代码和包装代码,如果我们使用python版Pytorch的话,与这些代码接触就比较密切了。

Caffe2则不用多说,caffe2则主要针对移动端设计了很多优化后的运算代码,模型融合、模型量化等等的代码,其后端有QNNPACK等一些针对移动端的底层运算库(有开发人员说GLOW也在caffe2后端考虑之内)。

third_party

Pytorch毕竟是大型的深度学习库,所以需要的依赖库也是有很多的,其中有很多我们耳熟能详的数值计算库(eigen、gemmlowp)、模型转换库(onnx、onnx-tensorrt)、并行训练库(gloo、nccl)、自家的底层端实现库(QNNPACK)以及绑定python端的pybind11等一系列所依赖的库。

当然还有很多库这里就不一一介绍了,总之,我们在编译的时候,Pytorch的编译代码会根据我们的设置在编译的时候,自动判断当前系统中是否存在需要的第三方库。如果不存在则使用这里的第三方库(直接编译并使用第三方库的diamante),这也是为什么我们需要执行git submodule update --init --recursive来下载所依赖第三库源码的原因。

tools

tools这个文件夹中的内容到底是做什么的,简单看一下官方的介绍:

代码语言:javascript复制
This folder contains a number of scripts which are used as
part of the PyTorch build process.  This directory also doubles
as a Python module hierarchy (thus the `__init__.py`).

其中包含了一些脚本生成代码工具(利用python)、用于编译一些组件的脚本和代码,还有一些开发人员需要的工具、以及AMD显卡帮助编译代码和一些特殊情况需要使用的工具等。在我们编译Pytorch源码的过程中会使用到这个文件夹中的代码。

有一点需要说明,那就是Pytorch利用了很多的代码生成,例如操作层函数的头文件NativeFunction.h等,所以tools中的代码生成脚本还是比较重要的。

提一个可能会使用到的脚本build_pytorch_libs.sh,这个脚本是用来编译libtorch库的,libtorch就是不需要python包装的使用C 的Pytorch库,方便于部署阶段使用。

关于libtorch的具体介绍和简单使用可以看这里:利用Pytorch的C 前端(libtorch)读取预训练权重并进行预测。

关于tools中的文件就不具体介绍了,大家可以看一下其中的readme

其他的文件夹就不多说了,相对上面的来说并不是很重要。

编译

编译重头戏来了,编译过程中大家可能会遇到各种各样的问题,但是其实只要我们将环境准备妥当,大部分都可以一次性编译好的:

  • 确保你的cuda和cudnn安装正确,环境变量都设置正确
  • 确保你的python环境纯净,最好使用anaconda创建一个环境,安装好pytorch需要的依赖包。 https://github.com/pytorch/pytorch#from-source
  • 确保你的C 编译器的版本不要太低,最好4.9以及以上

编译选项

python的安装方式并不是单独利用Cmake进行构建的,而是结合了python端的setuptools搭配cmake进行构建,pytorch的项目还是比较庞大的,所以编译代码也是老长,我们主要看看编译过程中的环境变量即可:

代码语言:javascript复制
# Environment variables you are probably interested in:
#
#   DEBUG
#     build with -O0 and -g (debug symbols)
#
#   REL_WITH_DEB_INFO
#     build with optimizations and -g (debug symbols)
#
#   MAX_JOBS
#     maximum number of compile jobs we should use to compile your code
#
#   NO_CUDA
#     disables CUDA build
#   
#   ....
#   ....
#   
# Environment variables for feature toggles:
#
#   NO_CUDNN
#     disables the cuDNN build
#
#   NO_FBGEMM
#     disables the FBGEMM build
#
#   NO_TEST
#     disables the test build
#
#   NO_MIOPEN
#     disables the MIOpen build

这些编译变量根据我们的需要在执行python setup.py install使用,如果你不想编译CUDA,则NO_CUDA=1 python setup.py install.

执行以上语句我们就可以进行编译了。

ninja

ninja可以大大加快编译速度,而且在编译过程中提示的错误信息更加完整和详细,如果我们想使用ninja来编译,那么直接在当前的python环境中pip install ninja即可。

Pytorch的安装程序会自动查找当前环境中是否有ninja,如果有的话,则优先使用ninja进行编译。

不同的安装模式

只安装libtorch库:创建build文件夹,在里头执行python ../tools/build_libtorch.py

开发者模式:python setup.py build develop(对Python开发有帮助)

安装后的自我检验

默认我们安装Pytorch的时候会自带上caffe2(当然也可以选择不安装caffe2,但是运行某些特定卷积操作时会报错~),因此我们在安装成功后不仅要检测Pytorch是否安装成功,同时也要检查caffe2是否安装成功。

pytorch

检查Pytorch安装是否成功:

代码语言:javascript复制
>>> import torch

>>> print(torch.cuda.is_available())
>>> print(torch.backends.cudnn.is_acceptable(torch.cuda.FloatTensor(1)))
... print(torch.backends.cudnn.version())```
True  # 出现Turn说明cuda正常
Ture  # 出现Ture说明cudnn正常
7401  # 这是我的版本号

caffe2

在安装caffe2的环境下运行python并导入caffe2.python,如果顺利加载则证明安装成功。如果不能成功import的话,可以先看看错误信息,很有可能是一些小错误,例如:

代码语言:javascript复制
Python 3.6.6 |Anaconda, Inc.| (default, Oct  9 2018, 12:34:16) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from caffe2.python import core
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/prototype/anaconda3/envs/pytorch-dev/lib/python3.6/site-packages/caffe2/python/__init__.py", line 2, in <module>
    from caffe2.proto import caffe2_pb2
  File "/home/prototype/anaconda3/envs/pytorch-dev/lib/python3.6/site-packages/caffe2/proto/caffe2_pb2.py", line 6, in <module>
    from google.protobuf.internal import enum_type_wrapper
ModuleNotFoundError: No module named 'google'

上方的导入出错是因为当期的虚拟环境没有安装protobuf,简单执行命令pip install protobuf即可,其他类似错误根据错误提示信息安装相应的库就可以了。

如果成功import则不会出现报错信息:

代码语言:javascript复制
Python 3.6.6 |Anaconda, Inc.| (default, Oct  9 2018, 12:34:16) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from caffe2.python import core
>>> 

如何卸载

如果是源码安装的Pytorch,卸载需要执行:

代码语言:javascript复制
pip uninstall torch
python setup.py clean

常见问题

ninja

如果遇到找不到build.ninja的问题,可以尝试重新安装ninja,或者不使用ninja即可。

没有相应的第三方库

如果你的cmake报告以下的错误:

代码语言:javascript复制
CMake Error at aten/src/ATen/CMakeLists.txt:225 (add_subdirectory):
  The source directory

    /home/prototype/Downloads/pytorch/third_party/sleef

  does not contain a CMakeLists.txt file.


CMake Error at aten/src/ATen/CMakeLists.txt:226 (set_property):
  set_property could not find TARGET sleef.  Perhaps it has not yet been
  created.

说明编译源码所需要的第三方库没有下载好,这时候需要执行git submodule update --init --recursive来更新第三方库源,下载好我们的第三方库即可。

授人以鱼不如授人以渔,最好的查询编译问题的地址还是GITHUB的issue界面,将你遇到的问题粘贴过去查询即可,基本你遇到其他人也遇到的问题都在这里了。

参考链接

https://pytorch.org/blog/a-tour-of-pytorch-internals-1/

https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md

0 人点赞