如何使用SSE4.2和AVX指令编译Tensorflow?

318

这是运行检查Tensorflow是否工作的脚本后收到的消息:

I tensorflow/stream_executor/dso_loader.cc:125] successfully opened CUDA library libcublas.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:125] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:125] successfully opened CUDA library libcufft.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:125] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:125] successfully opened CUDA library libcurand.so.8.0 locally
W tensorflow/core/platform/cpu_feature_guard.cc:95] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:95] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:910] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero

我注意到它提到了SSE4.2和AVX,

  1. SSE4.2和AVX是什么?
  2. SSE4.2和AVX如何改善Tensorflow任务的CPU计算?
  3. 如何使Tensorflow使用这两个库进行编译?

19
我喜欢使用这些标志进行构建 bazel build -c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-mfpmath=both --config=cuda -k //tensorflow/tools/pip_package:build_pip_package 在 Xeon E5 v3 上,与官方版本相比,8k矩阵乘法的CPU速度提高了3倍(0.35 -> 1.05 T ops/sec)。 - Yaroslav Bulatov
4
注意:对于gcc 5或更高版本,TensorFlow网站上提供的二进制pip软件包是使用gcc 4构建的,该软件包使用较旧的ABI。为了使您的构建与较旧的ABI兼容,您需要在bazel构建命令中添加--cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0"。ABI兼容性允许针对TensorFlow pip软件包构建的自定义操作继续针对您构建的软件包工作。 - Ivan Kush
5
我有一些编译好的二进制文件,支持这些指令 https://github.com/lakshayg/tensorflow-build。你可能会发现这很有用。 - lakshayg
1
@IvanKush 加入了那个标志后,我仍然无法成功导入tensorflow(编译正常)。如果您已经成功使用gcc 5编译,请参阅:https://dev59.com/q6Tja4cB1Zd3GeqPE6IT?noredirect=1#comment78712788_45877158 - anon01
1
如果使用Ubuntu 16.04,我们在https://github.com/mind/wheels上提供了几乎所有你可能需要的构建版本。 - danqing
显示剩余2条评论
12个回答

173

我也遇到了同样的问题,似乎 Yaroslav Bulatov 的建议并没有涵盖 SSE4.2 支持,加入 --copt=-msse4.2 即可。最终,我成功地构建了。

bazel build -c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-mfpmath=both --copt=-msse4.2 --config=cuda -k //tensorflow/tools/pip_package:build_pip_package

不出现任何警告或错误的最佳选择可能是:

bazel build -c opt --copt=-march=native --copt=-mfpmath=both --config=cuda -k //tensorflow/tools/pip_package:build_pip_package

(更新: 编译脚本可能会忽略-march=native,可能是因为它包含一个=号。))

-mfpmath=both 只能用于gcc,而不能用于clang。-mfpmath=sse 可能和默认的x86-64一样好甚至更好。32位的构建默认为-mfpmath=387,所以改变这个选项可以帮助32位的构建。(但是如果您想进行高性能数值计算,应该构建64位二进制文件。)

我不确定TensorFlow的默认值是-O2还是-O3gcc -O3启用全面优化,包括自动向量化,但有时会使代码变慢。


此操作:--copt 用于bazel build,将选项直接传递给gcc以编译C和C++文件(但不用于链接,因此需要不同的选项以实现跨文件链接时优化)

x86-64 gcc默认仅使用SSE2或更旧的SIMD指令,因此您可以在任何x86-64系统上运行二进制文件。(请参阅https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html)。但这不是您想要的。您需要创建一个利用CPU可运行的所有指令的二进制文件,因为您只在构建它的系统上运行此二进制文件。

-march=native启用CPU支持的所有选项,因此使-mavx512f -mavx2 -mavx -mfma -msse4.2冗余。(另外,-mavx2已经使-mavx-msse4.2可用,所以Yaroslav的命令应该没问题。)另外,如果您使用的CPU不支持其中某个选项(如FMA),使用-mfma将产生带有非法指令的二进制文件。

TensorFlow的./configure默认启用-march=native,因此使用它应该避免手动指定编译器选项。

-march=native启用-mtune=native,因此它会针对您的CPU进行优化,例如最适合非对齐加载的AVX指令序列。

这适用于gcc、clang或ICC。(对于ICC,可以使用-xHOST代替-march=native。)


7
确实起作用 > 加1!因此,似乎“-march=native”没有发挥作用。除此之外,如果不需要CUDA支持,则删除“--config=cuda”,并且由于编译过程中没有出现错误,因此也可以去掉“-k”。 - Marc
4
卸载并重新安装新编译的版本后,我仍然收到有关AVX、AVX2和FMA的警告。 - Benedikt S. Vogler
6
我必须删除 --copt=-mfpmath=both 以使其与 macOS 上的 clang 协同工作。这会影响生成的二进制文件吗? - gc5
2
仅供澄清:当我创建配置文件时...我是否只是使用--copt=-march=native?还是我要在我有选项放置优化的地方放置原始帖子中看到的所有优化? - Thornhale
1
我收到一个错误,说“build”命令只支持从工作区?该怎么办? - humble
显示剩余15条评论

140

让我们先解释一下为什么首次看到这些警告


很可能您没有从源代码安装TF,而是使用了类似于pip install tensorflow的内容。这意味着您安装了由其他人构建的预编译二进制文件,这些二进制文件并未针对您的架构进行优化。而这些警告正是告诉您这一点:某些内容可用于您的架构,但由于未编译二进制文件,因此无法使用。以下是文档的一部分。

TensorFlow在启动时检查它是否已使用CPU上的优化进行编译。如果未包含这些优化项,则TensorFlow将发出警告,例如:未包括AVX、AVX2和FMA指令。

好消息是,您很可能只是想学习/尝试TF,因此一切都会正常工作,您不必担心


SSE4.2和AVX是什么?

维基百科对SSE4.2AVX有很好的解释。了解这些知识并不是成为机器学习专家所必需的。您可以将它们视为一组某些额外的指令,使计算机能够针对单个指令使用多个数据点执行操作,从而实现自然并行化的操作(例如添加两个数组)。

SSE和AVX都是抽象思想SIMD的实现(单一指令,多数据),其中

是Flynn分类中的一类并行计算机。它描述具有多个处理元素的计算机,这些处理元素同时对多个数据点执行相同的操作。因此,这样的机器可以同时进行多项操作。

利用数据级别的并行性,而非并发性:有同时(并行)计算,但在给定时刻只有单个进程(指令)

这已足以回答你的下一个问题。


SSE4.2和AVX如何改善TF任务的CPU计算

它们允许更有效地计算各种向量(矩阵/张量)操作。您可以在这些幻灯片中了解更多信息。


如何使用这两个库编译Tensorflow?

您需要拥有一个已编译以利用这些指令的二进制文件。最简单的方法是自己编译。正如Mike和Yaroslav建议的那样,您可以使用以下bazel命令:

bazel build -c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-mfpmath=both --copt=-msse4.2 --config=cuda -k //tensorflow/tools/pip_package:build_pip_package


6
这个命令行是什么意思?在这种情况下,我应该安装 bazel 吗? - Y. Z.
1
有人曾经使用MSYS2或Visual Studio 2017社区版在Windows 64位下进行构建吗?能否分享一下步骤? - James Chang
1
这个pip包能否安装到本地机器上的conda环境中? - dgketchum
4
经过3个多小时的编译(经过时间:11984.258秒),我收到了“FAILED: Build did NOT complete successfully”的错误提示。自己编译并不是那么简单。 - imbrizi
文档链接已损坏。 - Peter Cotton
显示剩余2条评论

56

首先我回答你的第三个问题:

如果你想在conda-env中运行自己编译的版本,可以按照以下一般指示来安装tensorflow并在我的系统上添加额外的指示。注意:这个版本是为AMD A10-7850构建的(Ubuntu 16.04 LTS),请根据你的CPU支持的指令进行检查,可能会有所不同。我在conda-env中使用Python 3.5。感谢tensorflow源安装页和上面提供的答案。

git clone https://github.com/tensorflow/tensorflow 
# Install Bazel
# https://bazel.build/versions/master/docs/install.html
sudo apt-get install python3-numpy python3-dev python3-pip python3-wheel
# Create your virtual env with conda.
source activate YOUR_ENV
pip install six numpy wheel, packaging, appdir
# Follow the configure instructions at:
# https://www.tensorflow.org/install/install_sources
# Build your build like below. Note: Check what instructions your CPU 
# support. Also. If resources are limited consider adding the following 
# tag --local_resources 2048,.5,1.0 . This will limit how much ram many
# local resources are used but will increase time to compile.
bazel build -c opt --copt=-mavx --copt=-msse4.1 --copt=-msse4.2  -k //tensorflow/tools/pip_package:build_pip_package
# Create the wheel like so:
bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
# Inside your conda env:
pip install /tmp/tensorflow_pkg/NAME_OF_WHEEL.whl
# Then install the rest of your stack
pip install keras jupyter etc. etc.

关于你的第二个问题:

我认为编译优化后的自行编译版本非常值得努力。在我的特定设置上,以前需要560-600秒的计算现在只需要大约300秒!虽然确切的数字会有所不同,但我认为你可以在你特定的设置上期望大约35-50%的速度提升。

最后是你的第一个问题:

很多答案已经在上面提供了。 总结一下:AVXSSE4.1,SSE4.2,MFA是X86 CPU上不同类型的扩展指令集。其中许多包含用于处理矩阵或向量操作的优化指令。

我将强调自己的误解,希望能为您节省一些时间:SSE4.2并不是新的指令版本,超越了SSE4.1。SSE4 = SSE4.1(一组47个指令)+ SSE4.2(一组7个指令)。

在tensorflow编译的上下文中,如果您的计算机支持AVX2和AVX以及SSE4.1和SSE4.2,您应该将这些优化标志全部放入其中。不要像我一样只选择SSE4.2,认为它比SSE4.1新并应该替代SSE4.1。那显然是错误的!我因此不得不重新编译,花费了我好40分钟。


1
总的来说,我发现在Windows上进行机器学习非常麻烦。你会花费很多时间去尝试让一些在Linux环境下轻松完成的工作在Windows上正常运行。我相信TensorFlow需要为每个操作系统编译。此外,如果你访问这里:链接,你会发现TensorFlow并没有得到官方支持。虽然有一些关于如何在Windows上编译TensorFlow的指南在这里:链接。但是我必须承认,我没有尝试过。我只是使用Ubuntu。 - Thornhale
奇怪的是,正如amortazi所评论的那样,确保您从tensorflow存储库外执行pip3 install ...命令,否则它将无法正常工作! - reubenjohn
@Dmitry:正如我所提到的,您可以期望获得30-50%的速度提升。这种速度提升主要来自于使用AVX等矩阵操作的优化。 - Thornhale
但是当使用GPU时,速度并没有提高! - Dmitry
这是正确的,因为这样你就不会使用CPU矩阵运算,而是使用GPU资源。 - Thornhale
显示剩余8条评论

25

这些是 SIMD 向量化指令集 向量处理指令集

使用向量指令可以加快许多任务的速度;机器学习就是这样一项任务。

引用 tensorflow 安装文档的话:

为了兼容尽可能广泛的机器,TensorFlow 默认只在 x86 机器上使用 SSE4.1 SIMD 指令。大多数现代 PC 和 Mac 支持更高级别的指令,因此,如果您正在构建一个只在自己的机器上运行的二进制文件,您可以在 bazel 构建命令中使用 --copt=-march=native 来启用这些指令。


为什么Tensorflow二进制文件不使用CPU分派?这是GCC支持不好吗? - Chris Pushbullet
4
“tensorflow installation docs”这个链接无法打开,因此我想知道是否这个答案仍然有效。请回复! - Thornhale
@ChrisPushbullet 你可以编译Tensorflow以支持多种不同的GPU计算能力,但这会大大增加二进制文件的大小。我猜CPU也是一样的。 - Davidmh

22

在得到所有回复并经过一些尝试后,我成功地使用 clang 在Mac上安装了它。所以,如果对某人有用的话,我分享一下我的解决方案。

  1. 按照文档 - 从源码安装 TensorFlow中的说明进行操作

  2. 提示:

    请指定编译期间使用的优化标志,当 bazel 选项“--config=opt”被指定时[默认为 -march=native]

然后复制粘贴此字符串:

-mavx -mavx2 -mfma -msse4.2

默认选项导致了错误,其他一些标志也有问题。我使用上述标志没有出现错误。顺便说一下,我对所有其他问题都回答了n

安装后,我发现与另一个基于默认轮子的安装相比,在训练深度模型时速度提高了约2倍至2.5倍 - 在macOS上安装TensorFlow

希望这可以帮到你。


4
如果您的编译器正确支持,那么-march=native应该会更好。它还会设置-mtune=native以选择适合您的CPU的指令。例如,在Haswell和之后的版本上,它会禁用-mavx256-split-unaligned-store-mavx256-split-unaligned-load,这些选项在默认情况下对于-mtune=generic是开启的,并且当数据不对齐但在运行时被证明为对齐时会影响性能。 - Peter Cordes
1
谢谢!在我的情况下,-march=native 导致了错误,而其他选项则没有。也许是特定的编译器问题。我分享这个信息只是为了防止其他人遇到同样的障碍。 - JARS
1
什么错误?除非构建系统无法处理带有=的字符串,或者您没有使用gccclang,否则它应该可以工作。-mtune=native -mavx2 -mfma 对您有效吗?或者是-mtune=skylake?(或者您拥有的任何CPU)。顺便说一句,-mavx2意味着-mavx-msse4.2。在配方中包含所有这些选项不会伤害,我猜这样做可以让人们更容易地省略他们的CPU不支持的选项。 - Peter Cordes
1
我一段时间前编辑了这个问题的顶部答案,但我自己不使用tensorflow。如果-march=native对其构建系统有什么问题,我想知道。(或者你应该向上游报告,以便他们可以修复他们的构建脚本)。 - Peter Cordes
1
非常感谢您的建议。为了检查这个问题,我只使用-march=native重新运行了.configure脚本,但是出现了以下错误:/Users/jose/Documents/code/tmptensorflow/tensorflow/tensorflow/core/BUILD:1442:1: C++编译规则'//tensorflow/core:lib_internal_impl'失败(退出1)。 在文件包含中来自tensorflow/core/platform/denormal.cc:37: /Library/Developer/CommandLineTools/usr/bin/../lib/clang/7.0.2/include/pmmintrin.h:28:2: 错误:“SSE3指令集未启用” #error "SSE3 instruction set not enabled" 使用Apple LLVM版本7.0.2(clang-700.1.81) - JARS
在日志中,-march=native 是否实际上出现在编译器命令行中?唯一有道理的解释是构建脚本“吃掉”了该选项,可能是因为它包含一个 =。 (如果没有 -march=native,那么 #include <pmmintrin.h> 就会给出那个错误消息,而且 TensorFlow 需要 SSE3 作为基线也是有道理的。)难怪人们在构建 TensorFlow 时遇到这么多麻烦!!也许你可以尝试使用 '-march=native'(单引号内),或者 -march\=native - Peter Cordes

8

我最近从源代码安装了它,以下是所有安装步骤和相关说明。

其他答案已经解释了为什么会显示这些消息。我的回答提供了一个逐步安装的方法,这可能有助于像我一样在实际安装中遇到困难的人们。

  1. 安装Bazel

从可用的版本之一下载它,例如0.5.2。 解压缩后进入目录并进行配置:bash ./compile.sh。 将可执行文件复制到/usr/local/binsudo cp ./output/bazel /usr/local/bin

  1. 安装Tensorflow

克隆Tensorflow:git clone https://github.com/tensorflow/tensorflow.git 进入克隆的目录以进行配置:./configure

它会提示您几个问题,下面我建议对每个问题给出响应,当然,您可以根据自己的喜好选择自己的响应:

Using python library path: /usr/local/lib/python2.7/dist-packages
Do you wish to build TensorFlow with MKL support? [y/N] y
MKL support will be enabled for TensorFlow
Do you wish to download MKL LIB from the web? [Y/n] Y
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] n
jemalloc disabled
Do you wish to build TensorFlow with Google Cloud Platform support? [y/N] N
No Google Cloud Platform support will be enabled for TensorFlow
Do you wish to build TensorFlow with Hadoop File System support? [y/N] N
No Hadoop File System support will be enabled for TensorFlow
Do you wish to build TensorFlow with the XLA just-in-time compiler (experimental)? [y/N] N
No XLA JIT support will be enabled for TensorFlow
Do you wish to build TensorFlow with VERBS support? [y/N] N
No VERBS support will be enabled for TensorFlow
Do you wish to build TensorFlow with OpenCL support? [y/N] N
No OpenCL support will be enabled for TensorFlow
Do you wish to build TensorFlow with CUDA support? [y/N] N
No CUDA support will be enabled for TensorFlow
  1. pip包。要构建它,您需要描述您想要的指令(您知道的,那些Tensorflow告诉您缺少的指令)。

构建pip脚本:bazel build -c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-mfpmath=both --copt=-msse4.1 --copt=-msse4.2 -k //tensorflow/tools/pip_package:build_pip_package

构建pip包:bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg

安装您刚刚构建的Tensorflow pip包:sudo pip install /tmp/tensorflow_pkg/tensorflow-1.2.1-cp27-cp27mu-linux_x86_64.whl

现在下次启动Tensorflow时,它将不再抱怨缺少指令。


4
仅使用-c opt --copt=-march=native编译的效果应该至少与--copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-msse4.1 --copt=-msse4.2相同(两者都可以消除警告,但-march=native可能会通过专门为正在构建的系统上的CPU进行调整而获得更快的代码)。此外,请注意,--copt=-mavx2 --copt=-mfma包含所有早期的AVX和SSE选项,因此这个长字符串的选项显然是由不了解gcc选项的人编写的。 - Peter Cordes
1
@PeterCordes,请查看此问题(https://github.com/tensorflow/tensorflow/issues/7449)。即使是bazel维护者也不确定为什么-march = native不能按预期工作。由于您似乎“理解gcc选项”,因此您可能会帮助他们修复它,因为他们已将该问题标记为需要“社区支持”。 - Eduardo
谢谢,我会看一下... 嗯,有些人说 --copt=-mavx2 不起作用。如果 --copt=-mfma 起作用,--copt=-march=native 应该也可以,除非解析 = 的过程出现问题。对于 gcc/clang/icc,你肯定希望构建脚本最终将 -march=native 传递给编译器。通过构建脚本实现这一点成为技巧。 - Peter Cordes

7

这是最简单的方法。只需要一个步骤。

它对速度有重大影响。在我的情况下,训练一个步骤所需的时间几乎减半。

请参考TensorFlow的自定义构建版本


3
Windows版本包含AVX2指令集 https://github.com/fo40225/tensorflow-windows-wheel - Chris Moschini
@SreeraghAR 你的方法降级了我的tensorflow和keras。 - ajaysinghnegi
请确保根据您的TensorFlow、Python版本和硬件安装正确的文件。 - Sreeragh A R
@SreeraghAR 的 TensorFlow 版本是 1.10.0,正在使用 MacOS Sierra。请帮我找到该文件。 - ajaysinghnegi
哎呀.. 找不到与你的版本相对应的。必须有人要构建自定义wheel。 https://github.com/yaroslavvb/tensorflow-community-wheels即时解决方案可能是使用Tensorflow 1.9.0 - Sreeragh A R
正如@ChrisMoschini所提到的,卸载tensorflow包并从提供的存储库安装正确版本解决了我所有的问题。 - Alex Klaus

5

2
最近有什么变化吗? 我上次检查时,--copt="-march=native" 吃掉了 =。(而且顺便说一下,那些双引号没有任何作用;它们会被 shell 在 bazel 看到你的命令行之前移除。) - Peter Cordes

5

4

2.0 兼容解决方案:

在终端(Linux/MacOS)或命令提示符(Windows)中执行以下命令,使用Bazel安装Tensorflow 2.0:

git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow

#The repo defaults to the master development branch. You can also checkout a release branch to build:
git checkout r2.0

#Configure the Build => Use the Below line for Windows Machine
python ./configure.py 

#Configure the Build => Use the Below line for Linux/MacOS Machine
./configure
#This script prompts you for the location of TensorFlow dependencies and asks for additional build configuration options. 

#Build Tensorflow package

#CPU support
bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package 

#GPU support
bazel build --config=opt --config=cuda --define=no_tensorflow_py_deps=true //tensorflow/tools/pip_package:build_pip_package

3
这段话中有关于-march=native或其他GCC / clang选项的信息在哪里指定的问题。 我没有看到任何有关AVX,FMA或SSE4.2的提及。(Bazel或Tensorflow的构建脚本仍然存在问题吗,只能使用像-mavx这样的选项而不是-march=native?如果这是这个问题最好的答案所述的问题) - Peter Cordes
对于tf版本2.1.0的CPU支持,选项--config=opt对我无效,我用--config=v2解决了这个问题。同时,正确的bazel版本是29.0。 - Tolik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接