京東科技隱私計算產品部 曹雨晨
為什麼從原始碼構建
通常情況下,直接安裝構建好的.whl即可。不過,當需要一些特殊配置(或者閒來無事想體會 TensorFlow 構建過程到底有多麻煩)的時候,則需要選擇從原始碼構建TensorFlow。萬幸文件混亂的 TensorFlow 還是好心地為我們提供了一整頁的文件供參考 https://www.tensorflow.org/in... ,個人認為其中最需要關注的部分莫過於經過測試供參考的源配置(列於文末)。TF使用 Google 的開源構建工具 bazel 構建,並且原始碼的版本與 bazel 的版本高度相關,所以儘量匹配版本進行構建。
流程記錄 TF v1.14.0 CPU on Ubuntu 18.04
安裝對應版本的 bazel
根據計劃構建的版本,查閱文末的對應配置,參考官方文件: https://bazel.build/install/u... 安裝相應版本的 bazel,如本次計劃構建的版本是 v1.14.0,對應的 bazel 版本是 0.24.1(此次使用0.26.1也是可以的)。
為方便,這裡直接貼出對應 0.26.1 release 的頁面: https://github.com/bazelbuild... ,點選assets找到對應的檔案下載即可。
wget https://github.com/bazelbuild/bazel/releases/download/0.26.1/bazel-0.26.1-installer-linux-x86_64.sh
chmod +x bazel-version-installer-linux-x86_64.sh
./bazel-version-installer-linux-x86_64.sh --user
克隆 TensorFlow 倉庫
從 Github 上 clone
原始碼倉庫
git clone https://github.com/tensorflow/tensorflow
cd
到倉庫目錄並 git checkout
到相應 tag,比如這次是構建 v1.14.0 版本:
git checkout v1.14.0
* 一些小調整,通常可以略過
Build with C++17
因為之後需要寫的 Custom OP 依賴的另一個庫是 C++17,而除了剛剛才釋出的 v2.10 版,以前的 TF預設是使用 C++11,實際構建的時候,程式碼有一些 minor fix。此處參考 https://github.com/tensorflow... 修改 .bazelrc
裡 build:c++17
的配置,在 tensorflow/core/lib/gif/gif_io.cc
中新增 #include<cstring>
, 並在 tensorflow/stream_executor/stream_executor_pimpl.h
中新增 #include "absl/memory/memory.h"
(否則 compile 時會報錯找不到 absl::make_unique
)(這裡 make_unique 是 C++17 標準庫裡的用法,Google的abseil的make_unique方法則方便C++11的程式碼也可以使用它;最新的v2.10版由於預設使用C++17,已經改為std::make_unique)
.bazelrc
檔案裡記錄了構建時各種配置選項 ([--config=option]
)的對映規則,如有需要可以進行修改。由於 GCC 不支援--stdlib
命令,此次修改如下:
# Build TF with C++ 17 features.
- build:c++17 --cxxopt=-std=c++1z
- build:c++17 --cxxopt=-stdlib=libc++
+ build:c++17 --cxxopt=-std=c++17
網路不通
Bazel 在構建過程中,需要現拉取遠端倉庫的許多依賴。由於 TF 的構建過程消耗記憶體很嚴重,選擇在伺服器上進行構建,而伺服器遠端拉取 github 上倉庫經常失敗。所以需要手動在網路良好的機器上下載相應的庫的 release (對應的版本在 WORKSPACE
檔案中可以找到一行註釋),存放在伺服器本地,並在 WORKSPACE 檔案中對應的 http_archive
部分新增一行本地地址。若需要換版本,也可以在相應github庫的releases下面找到對應的 URL 及 sha256(實在是找不到對應的也可以手動下載壓縮包後透過 shasum256
命令獲取)
例如:
http_archive(
name = "build_bazel_rules_apple",
sha256 = "a045a436b642c70fb0c10ca84ff0fd2dcbd59cc89100d597a61e8374afafb366",
urls = ["https://github.com/bazelbuild/rules_apple/releases/download/0.18.0/rules_apple.0.18.0.tar.gz",
"file:///opt/tensorflow_build_deps/rules_apple.0.18.0.tar.gz"],
) # https://github.com/bazelbuild/rules_apple/releases
配置 build
執行原始碼根目錄下的 ./configure 進行配置。
./configure
此次編譯一個儘量簡略的 CPU 版本,會話如下:
WARNING: --batch mode is deprecated. Please instead explicitly shut down your Bazel server using the command "bazel shutdown".
You have bazel 0.26.1 installed.
Please specify the location of python. [Default is /usr/local/bin/python]:
Found possible Python library paths:
/usr/local/lib/python3.6/dist-packages
/usr/lib/python3/dist-packages
Please input the desired Python library path to use. Default is [/usr/local/lib/python3.6/dist-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.
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
構建 pip 軟體包並安裝
官方提供的命令:
bazel build [--config=option] //tensorflow/tools/pip_package:build_pip_package
本次使用:
bazel build --config=c++17 --config=c++1z --jobs=6 //tensorflow/tools/pip_package:build_pip_package
其中使用的 --config=c++17 --config=c++1z
對應剛剛修改的 .bazelrc 檔案中相應的部分
注意:bazel build
的過程時間會比較長,對記憶體的消耗較大,jobs 數謹慎開大。
bazel build
結束後,一個名為 build_pip_package
的可執行檔案就建立好了,接下來可以執行:
./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
如果希望構建的whl
名為 tf-nightly
版本,則可以加上 --nightly_flag
的選項。
./bazel-bin/tensorflow/tools/pip_package/build_pip_package --nightly_flag /tmp/tensorflow_pkg
此後便獲得了 .whl
檔案,透過 pip 安裝即可:
pip install /tmp/tensorflow_pkg/tensorflow-[version]-[tags].whl
其中,version
是對應的版本,tags
與系統有關。
經過測試的源配置
Linux
CPU
版本 | Python 版本 | 編譯器 | 構建工具 |
---|---|---|---|
tensorflow-2.6.0 | 3.6-3.9 | GCC 7.3.1 | Bazel 3.7.2 |
tensorflow-2.5.0 | 3.6-3.9 | GCC 7.3.1 | Bazel 3.7.2 |
tensorflow-2.4.0 | 3.6-3.8 | GCC 7.3.1 | Bazel 3.1.0 |
tensorflow-2.3.0 | 3.5-3.8 | GCC 7.3.1 | Bazel 3.1.0 |
tensorflow-2.2.0 | 3.5-3.8 | GCC 7.3.1 | Bazel 2.0.0 |
tensorflow-2.1.0 | 2.7、3.5-3.7 | GCC 7.3.1 | Bazel 0.27.1 |
tensorflow-2.0.0 | 2.7、3.3-3.7 | GCC 7.3.1 | Bazel 0.26.1 |
tensorflow-1.15.0 | 2.7、3.3-3.7 | GCC 7.3.1 | Bazel 0.26.1 |
tensorflow-1.14.0 | 2.7、3.3-3.7 | GCC 4.8 | Bazel 0.24.1 |
tensorflow-1.13.1 | 2.7、3.3-3.7 | GCC 4.8 | Bazel 0.19.2 |
tensorflow-1.12.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.15.0 |
tensorflow-1.11.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.15.0 |
tensorflow-1.10.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.15.0 |
tensorflow-1.9.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.11.0 |
tensorflow-1.8.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.10.0 |
tensorflow-1.7.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.10.0 |
tensorflow-1.6.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.9.0 |
tensorflow-1.5.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.8.0 |
tensorflow-1.4.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.5.4 |
tensorflow-1.3.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.5 |
tensorflow-1.2.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.5 |
tensorflow-1.1.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.2 |
tensorflow-1.0.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.2 |
GPU
版本 | Python 版本 | 編譯器 | 構建工具 | cuDNN | CUDA |
---|---|---|---|---|---|
tensorflow-2.6.0 | 3.6-3.9 | GCC 7.3.1 | Bazel 3.7.2 | 8.1 | 11.2 |
tensorflow-2.5.0 | 3.6-3.9 | GCC 7.3.1 | Bazel 3.7.2 | 8.1 | 11.2 |
tensorflow-2.4.0 | 3.6-3.8 | GCC 7.3.1 | Bazel 3.1.0 | 8.0 | 11.0 |
tensorflow-2.3.0 | 3.5-3.8 | GCC 7.3.1 | Bazel 3.1.0 | 7.6 | 10.1 |
tensorflow-2.2.0 | 3.5-3.8 | GCC 7.3.1 | Bazel 2.0.0 | 7.6 | 10.1 |
tensorflow-2.1.0 | 2.7、3.5-3.7 | GCC 7.3.1 | Bazel 0.27.1 | 7.6 | 10.1 |
tensorflow-2.0.0 | 2.7、3.3-3.7 | GCC 7.3.1 | Bazel 0.26.1 | 7.4 | 10.0 |
tensorflow_gpu-1.15.0 | 2.7、3.3-3.7 | GCC 7.3.1 | Bazel 0.26.1 | 7.4 | 10.0 |
tensorflow_gpu-1.14.0 | 2.7、3.3-3.7 | GCC 4.8 | Bazel 0.24.1 | 7.4 | 10.0 |
tensorflow_gpu-1.13.1 | 2.7、3.3-3.7 | GCC 4.8 | Bazel 0.19.2 | 7.4 | 10.0 |
tensorflow_gpu-1.12.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.15.0 | 7 | 9 |
tensorflow_gpu-1.11.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.15.0 | 7 | 9 |
tensorflow_gpu-1.10.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.15.0 | 7 | 9 |
tensorflow_gpu-1.9.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.11.0 | 7 | 9 |
tensorflow_gpu-1.8.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.10.0 | 7 | 9 |
tensorflow_gpu-1.7.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.9.0 | 7 | 9 |
tensorflow_gpu-1.6.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.9.0 | 7 | 9 |
tensorflow_gpu-1.5.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.8.0 | 7 | 9 |
tensorflow_gpu-1.4.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.5.4 | 6 | 8 |
tensorflow_gpu-1.3.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.5 | 6 | 8 |
tensorflow_gpu-1.2.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.5 | 5.1 | 8 |
tensorflow_gpu-1.1.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.2 | 5.1 | 8 |
tensorflow_gpu-1.0.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.4.2 | 5.1 | 8 |
macOS
CPU
版本 | Python 版本 | 編譯器 | 構建工具 |
---|---|---|---|
tensorflow-2.6.0 | 3.6-3.9 | Xcode 10.11 中的 Clang | Bazel 3.7.2 |
tensorflow-2.5.0 | 3.6-3.9 | Xcode 10.11 中的 Clang | Bazel 3.7.2 |
tensorflow-2.4.0 | 3.6-3.8 | Xcode 10.3 中的 Clang | Bazel 3.1.0 |
tensorflow-2.3.0 | 3.5-3.8 | Xcode 10.1 中的 Clang | Bazel 3.1.0 |
tensorflow-2.2.0 | 3.5-3.8 | Xcode 10.1 中的 Clang | Bazel 2.0.0 |
tensorflow-2.1.0 | 2.7、3.5-3.7 | Xcode 10.1 中的 Clang | Bazel 0.27.1 |
tensorflow-2.0.0 | 2.7、3.5-3.7 | Xcode 10.1 中的 Clang | Bazel 0.27.1 |
tensorflow-2.0.0 | 2.7、3.3-3.7 | Xcode 10.1 中的 Clang | Bazel 0.26.1 |
tensorflow-1.15.0 | 2.7、3.3-3.7 | Xcode 10.1 中的 Clang | Bazel 0.26.1 |
tensorflow-1.14.0 | 2.7、3.3-3.7 | Xcode 中的 Clang | Bazel 0.24.1 |
tensorflow-1.13.1 | 2.7、3.3-3.7 | Xcode 中的 Clang | Bazel 0.19.2 |
tensorflow-1.12.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.15.0 |
tensorflow-1.11.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.15.0 |
tensorflow-1.10.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.15.0 |
tensorflow-1.9.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.11.0 |
tensorflow-1.8.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.10.1 |
tensorflow-1.7.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.10.1 |
tensorflow-1.6.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.8.1 |
tensorflow-1.5.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.8.1 |
tensorflow-1.4.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.5.4 |
tensorflow-1.3.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.4.5 |
tensorflow-1.2.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.4.5 |
tensorflow-1.1.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.4.2 |
tensorflow-1.0.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.4.2 |
GPU
版本 | Python 版本 | 編譯器 | 構建工具 | cuDNN | CUDA |
---|---|---|---|---|---|
tensorflow_gpu-1.1.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.4.2 | 5.1 | 8 |
tensorflow_gpu-1.0.0 | 2.7、3.3-3.6 | Xcode 中的 Clang | Bazel 0.4.2 | 5.1 | 8 |