系统: 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
2
3
4
import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))

运行后有一个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性能也应该改善。

相关链接:

https://stackoverflow.com/questions/41293077/how-to-compile-tensorflow-with-sse4-2-and-avx-instructions

https://stackoverflow.com/questions/47068709/your-cpu-supports-instructions-that-this-tensorflow-binary-was-not-compiled-to-u

通过源码编译安装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

https://www.tensorflow.org/install/install_sources

意思是要把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

https://www.tensorflow.org/install/install_sources

我需要安装的是Python3.5版本的,因此,需要更改默认的Python包位置,更改内容如下:

1
2
3
4
5
6
7
Please specify the location of python. [Default is /usr/bin/python]: /usr/bin/python3.5
Found possible Python library paths:
/usr/local/lib/python3.5/dist-packages
/usr/lib/python3/dist-packages
Please input the desired Python library path to use. Default is [/usr/local/lib/python3.5/dist-packages]

也就是把/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

https://www.tensorflow.org/install/install_sources

在前言部分我们知道,我的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
2
sudo python3.5 -m pip uninstall enum
sudo python3.5 -m pip install enum34

后来提示又缺少了一个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.

https://www.tensorflow.org/install/install_sources

意思是说,默认情况下,从源构建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
2
3
INFO: Elapsed time: 10480.763s, Critical Path: 179.19s
INFO: 3757 processes, local.
INFO: Build completed successfully, 3918 total actions

第五步

运行命令:

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安装成功

注意

不要在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
2
3
4
5
6
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello).decode('utf-8'))
Hello, TensorFlow!
>>>

安装结束。