通过源码编译安装TensorFlow-CPU版本支持AVX等指令集
系统: ubuntu16.04 64位
Python3.5版本
tensorflow: 1.8(CPU版本)
bazel: bazel-0.13.1
注意:本文安装的是TensorFlow的CPU版本, 不是GPU版本的
前言
官网方法在Ubuntu上通过pip或者Virtualenv安装TensorFlow: https://www.tensorflow.org/install/install_linux
按照官网方法安装完成后测试安装结果:
1 | import tensorflow as tf |
运行后有一个Warning: your cpu supports instructions that this tensorflow binary was not compiled to use: avx2 fma
意思是提示我的CPU支持avx2和fma指令集,但是安装的TensorFlow版本没有编译使用。
在维基百科上看了下这个AVX指令集:
AVX指令集(英语:Advanced Vector Extensions,即高级向量扩展指令集)是x86架构处理器中的指令集,被英特尔和AMD的处理器所支持。AVX指令集由英特尔在2008年3月提出,并在2011年第一季度出品的Sandy Bridge系列处理器首获支持。随后,AMD在2011年第三季度的Bulldozer系列处理器也支持了AVX。
AVX是X86指令集的SSE延伸架构,如IA16至IA32般的把暂存器XMM 128bit提升至YMM 256bit,以增加一倍的运算效率。此架构支持了三运算指令(3-Operand Instructions),减少在编码上需要先复制才能运算的动作。在微码部分使用了LES LDS这两少用的指令作为延伸指令Prefix。
AVX2指令集将整数操作扩展到了256位,并引入了FMA指令集作为扩充。AVX-512则将指令进一步扩展到了512位。
看的不太懂,不过这里有一个更直接的介绍:
除了通常的算术和逻辑,现代CPU提供了许多低级指令,称为扩展,例如, SSE2,SSE4,AVX等
高级矢量扩展(AVX)是英特尔在2008年3月提出的英特尔和AMD微处理器的x86指令集体系结构的扩展,英特尔首先通过Sandy Bridge处理器在2011年第一季度推出,随后由AMD推出Bulldozer处理器在2011年第三季度.AVX提供了新功能,新指令和新编码方案。
特别是,AVX引入了融合乘法累加(FMA)操作,加速了线性代数计算,即点积,矩阵乘法,卷积等。几乎所有机器学习训练都涉及大量这些操作,因此将会支持AVX和FMA的CPU(最高达300%)更快。该警告指出您的CPU确实支持AVX(hooray!)。在此强调一下:
这只限于CPU。如果你有一个GPU,你不应该关心AVX的支持,因为大多数昂贵的操作将被分派到一个GPU设备上(除非明确地设置)。在这种情况下,您可以简单地忽略此警告。
那为什么会出现这种警告呢?
由于tensorflow默认分布是在没有CPU扩展的情况下构建的,例如SSE4.1,SSE4.2,AVX,AVX2,FMA等。默认版本(来自pip install tensorflow的版本)旨在与尽可能多的CPU兼容。另一个观点是,即使使用这些扩展名,CPU的速度也要比GPU慢很多,并且期望在GPU上执行中型和大型机器学习培训。
如果您没有GPU并且希望尽可能多地利用CPU,那么如果您的CPU支持AVX,AVX2和FMA,则应该从针对CPU优化的源构建tensorflow。在这个问题中已经讨论过这个问题,也是这个GitHub问题。 Tensorflow使用称为bazel的ad-hoc构建系统,构建它并不是那么简单,但肯定是可行的。在此之后,不仅警告消失,tensorflow性能也应该改善。
相关链接:
通过源码编译安装TensorFlow-CPU版本支持AVX等指令集
建议提前完整看一遍官网方法,在Ubuntu上通过源码安装TensorFlow:https://www.tensorflow.org/install/install_sources
注意事项:
- 分清楚Tensorflow的CPU版本和GPU版本, 本文使用的是CPU版本
- 分清楚要使用Python2.7还是3.x来学习使用TensorFlow, 本文使用的是3.x
第一步
新建目录: mkdir tf
,
进入到该目录下: cd tf
使用git来clone最新的TensorFlow的源码:git clone https://github.com/tensorflow/tensorflow
下载完成后,进入到tensorflow的目录里: cd tensorflow
注意: 这里官网提示:
The preceding git clone command creates a subdirectory named tensorflow. After cloning, you may optionally build a specific branch (such as a release branch) by invoking the following commands:
$ cd tensorflow
$ git checkout Branch # where Branch is the desired branch
For example, to work with the r1.0 release instead of the master release, issue the following command:$ git checkout r1.0
意思是要把git 分支切换到r1.0,
但是后面要使用bazel来编译,如果安装的bazel比较新,比如我安装的是bazel-0.13.1-installer-linux-x86_64.sh
,在切换r1.0分支后bazel编译的时候会报错:Current Bazel version is 0.13.1, expected at least 0.5.4,
详细讨论看这里:https://github.com/tensorflow/tensorflow/issues/16654
因此,这里选择不切换分支,使用默认分支master。
第二步
安装Bazel, 官网安装方法:https://docs.bazel.build/versions/master/install-ubuntu.html
安装完成后,使用命令bazel version
, 如果出现:Build label: 0.13.1
这样的就表示安装好了
然后安装TensorFlow Python dependencies,命令为:sudo apt-get install python3-numpy python3-dev python3-pip python3-wheel
第三步
进入到tensorflow源码的根路径,也就是:tensorflow文件夹下面,里面有一个configure
的文件,执行命令: ./configure
注意:
官方文档上选择默认安装的是Python版本是2.7,而且我Ubuntu系统默认的Python版本也是2.7的,会提示如下:
Please specify the location of python. [Default is /usr/bin/python]: /usr/bin/python2.7
Found possible Python library paths:
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
Please input the desired Python library path to use. Default is [/usr/lib/python2.7/dist-packages]Using python library path: /usr/local/lib/python2.7/dist-packages
我需要安装的是Python3.5版本的,因此,需要更改默认的Python包位置,更改内容如下:
1 | Please specify the location of python. [Default is /usr/bin/python]: /usr/bin/python3.5 |
也就是把/usr/bin/python2.7改成/usr/bin/python3.5, 如果系统默认的Python版本是3.x的,那就不需要改了。
其中有一个问题:
Please specify optimization flags to use during compilation when bazel option “–config=opt” is specified [Default is -march=native]:
这个选择默认的,直接回车
接下来是一些选项,参考了网上别人的选择的,除了第一个:Do you wish to use jemalloc as the malloc implementation? [Y/n] 选择的y,其他后面的都是选择了n,
最后提示:Configuration finished表示这一步完成
第四步
Build the pip package
把这一步完整读完再运行命令
注意:
官网上这一步的介绍是这样的:
To build a pip package for TensorFlow with CPU-only support, you would typically invoke the following command:
$ bazel build –config=opt //tensorflow/tools/pip_package:build_pip_package
在前言部分我们知道,我的CPU支持AVX,AVX2和FMA指令集来加快计算,所以可以在使用源码安装TensorFlow时候加入bazel参数使其支持AVX等指令集。
具体内容阅读这个回答: https://stackoverflow.com/questions/41293077/how-to-compile-tensorflow-with-sse4-2-and-avx-instructions
因此,不使用官网介绍的命令,而是使用如下命令:
1 | bazel build -c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-msse4.1 --copt=-msse4.2 -k //tensorflow/tools/pip_package:build_pip_package --local_resources 2048,.5,1.0 |
重要注意:
第一个:
我这次在漫长的等待后,最后提示:INFO: Build NOT completed successfully,
这是第二次失败,原因是缺少了enum
这个包:ImportError: No module named enum
用sudo python3.5 -m pip install enum
后,
又会报错:AttributeError: 'int' object attribute '__doc__' is read-only
,
在这里找到解决方法: https://github.com/tensorflow/tensorflow/issues/12491
不使用enum, 而是使用enum34, 因此:
1 | sudo python3.5 -m pip uninstall enum |
后来提示又缺少了一个mock包:ImportError: No module named mock 安装即可
在运行下面命令之前,把这两个enum34和mock安装好。
第二个:
官网介绍:
By default, building TensorFlow from sources consumes a lot of RAM. If RAM is an issue on your system, you may limit RAM usage by specifying –local_resources 2048,.5,1.0 while invoking bazel.
意思是说,默认情况下,从源构建TensorFlow将消耗大量的RAM。 如果RAM是您系统中的问题,则可以通过在调用bazel时指定–local_resources 2048,.5,1.0来限制RAM使用。
我第一次没有加--local_resources 2048,.5,1.0
这个指令,过了好久以后系统彻底卡死了,鼠标键盘都动不了,bazel build失败了,,然后又加了这个指令限制RA使用,不过虽然系统不卡了,但是build的过程非常慢,差不多有3个多小时。。
其他注意:
第一个: 命令很长,要完整复制
第二个: 这个过程非常慢,耐心等待。。。。。。。
第四个: 在stackoverflow里回答者的命令不太一样,多了一个--copt=-mfpmath=both
和--config=cuda
这两个,前一个不知道是什么作用,后面一个是安装GPU使用的,在第一次bazel build失败后,第二次这两个我都没有加。
最后完成后的成功提示:
1 | INFO: Elapsed time: 10480.763s, Critical Path: 179.19s |
第五步
运行命令:
1 | bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg |
会在/tmp/tensorflow_pkg这个路径下创建一个tensorflow-1.8.0-cp35-cp35mu-linux_x86_64.whl文件
然后运行命令:
1 | sudo python3.5 -m pip install /tmp/tensorflow_pkg/tensorflow-1.8.0-cp35-cp35mu-linux_x86_64.whl |
顺利安装成功
注意:
在第三步,运行./configure
命令时候,提示需要选择Python的版本及对应包的位置。我选的是Python3.5的,所以最后会创建一个tensorflow-1.8.0-cp35-cp35mu-linux_x86_64.whl文件, 如果当时选的是默认的2.7版本,那么继续执行到最后会创建一个tensorflow-1.8.0-cp27-cp27mu-linux_x86_64.whl文件,安装的也是Python2的tensorflow。
如果当时选的是2.7版本,然后又想在Python3下学习tensorflow,不要运行
1 | sudo python3.5 -m pip install /tmp/tensorflow_pkg/tensorflow-1.8.0-cp27-cp27mu-linux_x86_64.whl |
会报错:tensorflow-1.8.0-cp27-cp27mu-linux_x86_64.whl is not a supported wheel on this platform.
因为你bazel build的时候,使用的都是2.7版本对应的包,
正确的做法是在回到第三步,重新运行./configure
,然后选择Python3的版本,然后重新bazel build,直到最后生成tensorflow-1.8.0-cp35-cp35m-linux_x86_64.whl(Python3.5版本)或者tensorflow-1.8.0-cp36-cp36m-linux_x86_64.whl(Python3.6版本),最后再用pip install 对应的whl文件
第六步
最后来测试是否成功安装的tensorflow,打开终端,测试如下:
注意
不要在tensorflow的根目录,也就是configure同级目录下,否则会报错:
ImportError: Could not import tensorflow. Do not import tensorflow from its source directory; change directory to outside the TensorFlow source tree, and relaunch your Python interpreter from there.
对应Python3版本,print()输出的是b'Hello, TensorFlow!'
, 这个不是错误,具体解释看这里:
https://stackoverflow.com/questions/46213441/why-do-strings-returned-by-tensorflow-show-up-with-a-b-prefix-in-python-3
如果有强迫症要完美输出Hello, TensorFlow!
,可以在print的时候加一个decode("utf-8")
1 | import tensorflow as tf |
安装结束。