去落格博客阅读完整排版的在 macOS 上编译 Tensorflow 以开启 AVX2 和 FMA
最近更新:18th 一月, 2020
在使用 Tensorflow 时,一直有一个奇怪的警告:
Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
,虽然不影响使用,但看着很烦,你可以用这个命令关闭它:
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
。
不过,你有注意到吗?“
could speed up CPU computations
”……嗯?!
背景
总之,根据官方所述,Tensorflow 默认不支持这些高级功能是为了增强 Tensorflow 框架的兼容性,让它能够尽可能地在更多平台使用,从而避免不必要的编译操作。但这样的代价就是只能使用各个 CPU 平台都有的指令集,而高级命令就不能添加,毕竟不同的 CPU 平台它们有不同的高级指令集技术。
由于我使用 macOS,GPU 是 AMD,所以使用 Tensorflow 就别想用 GPU 进行加速了,用 CPU 又很慢,就只能跑测试数据(体积小),但我还是希望它能快一点。
所以 Tensorflow 提示我,针对我的 CPU 来说,有更高级的功能可以开启以加速训练——但怎么开启呢?答案肯定是用源码重新编译 Tensorflow。
AVX2 和 FMA
FMA 是现代 CPU 支持的一种高级指令集,中文叫“积和熔加运算”;
AVX 是现代 CPU 支持的“高级向量扩展指令集”,显然,这个 AVX2 的意思就是 AVX 进阶版的意思,它引入了上文的 FMA 运算,并将浮点性能提升 2 倍。
总之,如果 Tensorflow 能够直接使用这些高级功能,那训练速度一定能快上不少,接下来,我们就试试从头开始编译一个 Tensorflow。
准备工作
Python
显然,我们要用 Python 来使用 Tensorflow,所以你需要有 Python 环境:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
brew install python
这里我们使用 Brew 安装 Python3.
接下来是安装必要的依赖包:
pip3 install -U --user pip six numpy wheel setuptools mock 'future>=0.17.1'
pip3 install -U --user keras_applications --no-deps
pip3 install -U --user keras_preprocessing --no-deps
如果你使用 pip 有问题,不妨参考一下我的这一篇文章:正确使用 PIP 安装 Python 包 避免 TypeError: ‘module’ object is not callable
源码
要从源码编译 Tensorflow,就肯定要下载它的源码,找到一个你喜欢的目录位置,执行列命令获取 Tensorflow 项目源码:
git clone https://github.com/tensorflow/tensorflow.git
,进入目录
cd tensorflow
,我们要切换到稳定版分枝,首先到
https://github.com/tensorflow/tensorflow/releases查找最新的稳定版标签,就本文撰写之时,稳定版标签是
v2.1.0
,这里我们切换到稳定版:
git checkout v2.1.0
.
Bazel
Tensorflow 是要使用 Bazel 来编译的,整体编译过程轻松简单,但安装 Bazel 却需要一点点小技巧。
首先,检查你的 Tensorflow 源代码文件
tensorflow/configure.py
,在其中大概 53 行的位置,有一行
_TF_MAX_BAZEL_VERSION = '0.29.1'
,这就是我们要用的 Bazel 版本。
请注意:Bazel 最新版是 2.0,直接使用 brew 安装 bazel 是无法编译 Tensorflow 的。
首先要确保你的 macOS 安装了最新版的 Xcode,然后执行命令:
sudo xcodebuild -license accept
,然后到
https://github.com/bazelbuild/bazel/releases下载 Bazel 安装包,注意文件名应该是这样的:
bazel-0.29.1-installer-darwin-x86_64.sh
。
点击上文文件名链接直接下载指定版本的 bazel 安装包,将来 Tensorflow 源代码编译要求可能会变,到时候读者请自行对应 bazel 版本号。
由于 macOS 10.15 加强了系统安全措施,所以如果你直接执行脚本, bazel 是无法完成安装的,会提示类似“bazel 是有未知开发者发布,可能有害”之类的警告,从而拒绝运行。
使用命令:
sudo spctl --master-disable
暂时关闭这个警告,允许运行任意开发者的程序。
关闭警告后,就可以安装和使用 Bazel 了:
sh bazel-0.29.1-installer-darwin-x86_64.sh --user
,安装完成后使用
bazel --version
查看,结果应该是:
bazel 0.29.1
编译 Tensorflow
最终,我们可以进行编译了,回到 tensorflow 目录,执行
./configure
进行配置,它会询问你 Python 及其库的位置,如果你不是用 brew 安装的,那么可以用如下命令找到你 Python 的位置:
$ where python3
/usr/local/bin/python3
/usr/bin/python3
如果有多个结果,就选第一个即可。
$ ./configure
WARNING: --batch mode is deprecated. Please instead explicitly shut down your Bazel server using the command "bazel shutdown".
You have bazel 0.29.1 installed.
Please specify the location of python. [Default is /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python]: /usr/local/bin/python3
Found possible Python library paths:
/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages
Please input the desired Python library path to use. Default is [/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages]
Do you wish to build TensorFlow with XLA JIT support? [Y/n]: n
No XLA JIT support will be enabled for TensorFlow.
Do you wish to build TensorFlow with OpenCL SYCL support? [y/N]: n
No OpenCL SYCL support will be enabled for TensorFlow.
Do you wish to build TensorFlow with ROCm support? [y/N]: n
No ROCm 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.
Do you wish to download a fresh release of clang? (Experimental) [y/N]: n
Clang will not be downloaded.
Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native -Wno-sign-compare]:
Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: n
Not configuring the WORKSPACE for Android builds.
Do you wish to build TensorFlow with iOS support? [y/N]: y
iOS support will be enabled for TensorFlow.
Preconfigured Bazel build configs. You can use any of the below by adding "--config=<>" to your build command. See .bazelrc for more details.
--config=mkl # Build with MKL support.
--config=monolithic # Config for mostly static monolithic build.
--config=ngraph # Build with Intel nGraph support.
--config=numa # Build with NUMA support.
--config=dynamic_kernels # (Experimental) Build kernels into separate shared objects.
--config=v2 # Build TensorFlow 2.x instead of 1.x.
Preconfigured Bazel build configs to DISABLE default on features:
--config=noaws # Disable AWS S3 filesystem support.
--config=nogcp # Disable GCP support.
--config=nohdfs # Disable HDFS support.
--config=nonccl # Disable NVIDIA NCCL support.
Configuration finished
接下来的参数配置几乎无需设定,全部默认即可,我们不需要 GPU 支持(添加了也没用),不过最后有个 iOS 支持,这里我选择了 y,全部通过后,配置完成,就可以进行编译了。
使用命令
bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package
编译 Tensorflow 安装包,默认编译命令就是针对本地 CPU 进行编译,也就是启用所有当前 CPU 支持的指令集,这样编译出来的 Tensorflow 就是加速的啦!
编译过程很慢,在我 16G 内存 2.5 GHz Quad-Core Intel Core i7 CPU 下要 36301 秒能完成,整整 10 小时(给错了参数,10小时完全浪费了)要54219.95秒才能完成,整整15个小时(15 年中款 15寸rmbp)!
INFO: Elapsed time: 54219.950s, Critical Path: 1802.92s
INFO: 22004 processes: 22004 local.
INFO: Build completed successfully, 22776 total actions
另,我在编译时看到了这个警告:
external/eigen_archive/unsupported/Eigen/CXX11/../../../Eigen/src/Core/util/ConfigureVectorization.h:300:10: warning: "Disabling AVX support: clang compiler shipped with XCode 11.[012] generates broken assembly with -macosx-version-min=10.15 and AVX enabled. " [-W#warnings]
我还以为无法支持 AVX 要再来一遍呢……但似乎并不影响最终效果。
生成安装包
使用命令
./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
来生成
.whl
安装包:
$ ./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
Sat Jan 18 03:59:17 AEST 2020 : === Preparing sources in dir: /var/folders/dn/p_qzcyss2m3gdnkkyl_bw_d00000gn/T/tmp.XXXXXXXXXX.MxFJDO4r
~/Downloads/tensorflow ~/Downloads/tensorflow
~/Downloads/tensorflow
/var/folders/dn/p_qzcyss2m3gdnkkyl_bw_d00000gn/T/tmp.XXXXXXXXXX.MxFJDO4r/tensorflow/include ~/Downloads/tensorflow
~/Downloads/tensorflow
Sat Jan 18 03:59:32 AEST 2020 : === Building wheel
warning: no files found matching 'README'
warning: no files found matching '*.pyd' under directory '*'
warning: no files found matching '*.pd' under directory '*'
warning: no files found matching '*.so.[0-9]' under directory '*'
warning: no files found matching '*.dll' under directory '*'
warning: no files found matching '*.lib' under directory '*'
warning: no files found matching '*.csv' under directory '*'
warning: no files found matching '*.h' under directory 'tensorflow_core/include/tensorflow'
warning: no files found matching '*' under directory 'tensorflow_core/include/third_party'
Sat Jan 18 04:00:00 AEST 2020 : === Output wheel file is in: /tmp/tensorflow_pkg
然后我们用 pip 安装它:
pip install /tmp/tensorflow_pkg/tensorflow-2.1.0-cp37-cp37m-macosx_10_15_x86_64.whl
最后,可别忘了开启之前关闭了的安全警告:
sudo spctl --master-enable
测试安装结果
$ python3
Python 3.7.6 (default, Dec 30 2019, 19:38:26)
[Clang 11.0.0 (clang-1100.0.33.16)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> t = tf.constant('logcg')
2020-01-18 20:04:43.088104: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x7fefdc983db0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2020-01-18 20:04:43.088134: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version
现在已经不再提示
Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
了,尝试跑个模型,终于达到了可以忍耐的时长。
:)
参考文献
在 macOS 上编译 Tensorflow 以开启 AVX2 和 FMA,首发于落格博客。