CUDA

TensorFlow 2.2.0のビルド方法(tf2.2.0-rc0, CUDA 10.2, cuDNN 7.6.5, Windows 10)

Windows環境でTensorFlow v2.2.0-rc0をCUDA 10.2向けにビルドする手順を残しておきます。
公式サイトのビルド手順も分かりやすくなってきているので、必要に応じてご参照ください。
以前に古いバージョンのビルド方法(tf1.12.0+CUDA10.0tf1.13.1+CUDA10.1)についても紹介してきましたが、tf2ではビルド手順が改善されて簡単になっています。

ビルド環境(前提)

TensorFlow 2.2.0-rc0のビルドには以下の環境を使用しました。
前回まではIntelのCPUを使っていましたが、今回はAMDのCPUに変わっています。

  • CPU: AMD Threadripper 3960X
  • GPU: nVIDIA TITAN RTX
  • Windows 10 Pro – 64bit (Version 1909 build 18363.720)
  • CUDA 10.2 + cuDNN 7.6.5 (導入方法はこちらを参照)
  • Visual Studio Community 2019 – Ver16.4.6(導入方法はこちらを参照)
  • Python 3.8.2(python.orgのサイトからダウンロードしてインストール)

また、CUDAやcuDNN(C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin)、CUPTI(C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\extras\CUPTI\lib64)、Pythonへのパスを通しておく(システム環境変数のPATHに追加しておく)必要があります。
公式サイトではCUDAのincludeフォルダにもパスを通すように説明がありますが、includeフォルダはパスを通さなくても問題なくビルドできました。

ビルド環境の作成

TensorFlowのビルドには、上記環境に加えてMSYS2Bazelの導入が必要になります。それぞれ、以下の手順に従って環境を作成します。

MSYS2のインストール

MSYS2のサイトからセットアップファイル(msys2-x86_64-20190524.exe)をダウンロードしてインストールします。インストールが完了したら、MSYS2のbinフォルダ(C:\msys64\usr\bin)にパスを通してください。

C:\msys64\msys2_shell.cmdを実行してMSYS2のコンソールを開き、以下の手順でパッケージの更新や、必要なパッケージの導入を行います。

# パッケージ更新(C:\msys64\msys2_shell.cmdで開いたコンソールで)
pacman -Syu

# コンソールを再起動(×ボタンなどで閉じてOK)
# 新しく開いたコンソールで必要なパッケージの導入
pacman -Su
pacman -S git patch unzip

# 以降はMSYS2のコンソールを利用しないのでexitで終了
exit

Bazelの導入

TensorFlowのビルドには以前からBazelが使われているため、ビルドするTensorFlowのバージョンに対応したバージョンのBazelをダウンロードします。
利用するBazelのバージョンは、古くても新しくてもダメで、TensorFlowのconfigure.pyに書かれている_TF_MIN_BAZEL_VERSION_TF_MAX_BAZEL_VERSIONのバージョンを使う必要があります。

今回ビルドするTensorFlow v2.2.0-rc0の場合は「Bazel 2.0.0」しか使えないので注意が必要です。

Bazel 2.0.0をダウンロードし、ファイル名をbazel.exeに変更してパスの通ったフォルダに格納します。今回は、C:\Toolsフォルダにパスを通し、このフォルダにbazel.exeを格納しています。

以前のバージョンでは必要だったBAZEL_SHBAZEL_VC環境変数定義は不要になっていました。

ロングパスの設定

ファイル名を指定して実行(Windowsキー+R)でgpedit.mscを実行して、ローカルグループポリシーエディターを起動します。
コンピューターの構成>管理者用テンプレート>システム>ファイルシステムを選択し、その中にある「Win32の長いパスを有効にする」を「有効」に変更します。

TensorFlow 2.2.0-rc0のビルド

以下の手順でTensorFlowをソースコードからビルドしていきます。
今回はビルド用のPython仮想環境としてg:\venvs\build_tf2を使用する前提です。

ビルド用のPython仮想環境作成

Visual Studio 2019のx64 Native Tools Command Prompt for VS 2019を起動してコンソール画面を開き、ビルド用のPython環境を作成します。以降の操作は、このコンソール画面を使います。

# 仮想環境を作成して有効化する
python -m venv g:\venvs\build_tf2
cd /d g:\venvs\build_tf2
g:\venvs\build_tf2\Scripts\activate.bat

# pipのアップグレード(任意)
python -m pip install --upgrade pip

# ビルドに必要なパッケージを導入
pip install six numpy wheel
pip install keras_applications==1.0.8 --no-deps
pip install keras_preprocessing==1.1.0 --no-deps

ソースコードの取得

gitを使ってソースコードを取得します。ソースコードはg:\venvs\build_tf2\tensorflowフォルダ配下にダウンロードします。

# build_tf2フォルダで作業する
cd /d g:\venvs\build_tf2

# TensorFlow v2.2.0-rc0のソースコードを取得
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
git checkout v2.2.0-rc0

ビルド構成の設定

利用環境に合わせてビルド構成を設定します。

NVIDIA TITAN RTXでCUDAを使うため、次のような設定にしています。利用するGPUによってCUDAのCompute capabilityの値が異なるため、詳細はnVIDIAのページを確認してください。
設定では何も入力せずにEnterキーを押せばデフォルト設定(Yes/Noの場合は大文字で表示されている値がデフォルト)が利用されます。

Location of Python(Enter – デフォルト)
ROCm support(Enter – デフォルト=N)
CUDA supportY
CUDA compute capabilities7.5
Optimization flag/arch:AVX2
Override eigen…(Enter – デフォルト=Y)
python ./configure.py
(build_tf2) G:\venvs\build_tf2\tensorflow>python ./configure.py
Extracting Bazel installation...
You have bazel 2.0.0 installed.
Please specify the location of python. [Default is g:\venvs\build_tf2\Scripts\python.exe]:


Found possible Python library paths:
  g:\venvs\build_tf2\lib\site-packages
Please input the desired Python library path to use.  Default is [g:\venvs\build_tf2\lib\site-packages]

Do you wish to build TensorFlow with ROCm support? [y/N]:
No ROCm support will be enabled for TensorFlow.

Do you wish to build TensorFlow with CUDA support? [y/N]: y
CUDA support will be enabled for TensorFlow.

Found CUDA 10.2 in:
    C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.2/lib/x64
    C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.2/include
Found cuDNN 7 in:
    C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.2/lib/x64
    C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.2/include


Please specify a list of comma-separated CUDA compute capabilities you want to build with.
You can find the compute capability of your device at: https://developer.nvidia.com/cuda-gpus.
Please note that each additional compute capability significantly increases your build time and binary size, and that TensorFlow only supports compute capabilities >= 3.5 [Default is: 3.5,7.0]: 7.5


Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is /arch:AVX]: /arch:AVX2


Would you like to override eigen strong inline for some C++ compilation to reduce the compilation time? [Y/n]:
Eigen strong inline overridden.

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.

設定時に、環境設定の内容が全てコマンドラインのパラメータで渡されているため、環境変数が大量に設定されている場合や、ビルドのパス名が長い場合など、パラメータの文字数が32768文字を超えて、FATAL: Command line too long (34052 > 32768)というようなエラーが発生する場合があります。

このパラメータ数の制約はOS側の制約だと思われるため、開いているコンソール画面で不要な環境変数を次のように削除して、パラメータの文字数が32768文字以下になるようにします。Pythonのactivate.batを使っている場合、環境変数_OLD_VIRTUAL_PATHにdeactivate用のパスが入っており、この環境変数が文字数を大量に使っていると思われるため、まずは_OLD_VIRTUAL_PATHから削ってみると良いと思います。

なお、コンソール画面で削除した環境変数は、使っているコンソール画面のみで有効です。そのためOSに設定してある元の環境設定自体が消えたり、書き換わることはありません。

# _OLD_VIRTUAL_PATH の環境変数を無効にする方法
set _OLD_VIRTUAL_PATH=

ビルド

次のコマンドでTensorFlowのビルドを行います。
なお、以前はKasperskyなどのセキュリティソフトが有効になっていると、ビルド時のファイルダウンロードが失敗してエラーになっていましたが、今回はKaspersky(v20.0.14)を有効にしたままでも問題なくビルドできました。

bazel build --config=opt --config=cuda --define=no_tensorflow_py_deps=true --copt=-nvcc_options=disable-warnings //tensorflow/tools/pip_package:build_pip_package

利用している環境によっても違いますが、ビルド完了まで数十分~数時間かかります。ビルドが完了すると、次のようにメッセージが表示されます。

INFO: Elapsed time: 1648.998s, Critical Path: 639.86s
INFO: 8669 processes: 8669 local.
INFO: Build completed successfully, 12517 total actions

Wheelパッケージの作成

Python用のwheelパッケージを作成します。
今回はg:\tensorflow_pkgフォルダ配下にパッケージを作成します。なお、指定したフォルダは自動で作成されるため、あらかじめ作成しておく必要はありません。

完了すると、指定したフォルダにtensorflow-2.2.0rc0-cp38-cp38-win_amd64.whl(環境によってファイル名は少し変わる)が作成されます。

# g:\tensorflow_pkgフォルダにパッケージを作成する(数分かかる)
bazel-bin\tensorflow\tools\pip_package\build_pip_package g:\tensorflow_pkg

不要ファイルの削除(オプション)

TensorFlowのビルド作業は、これで完了です。コンソールはexitで終了してかまいません。

ビルド時に作成されたBazelのワークファイルは%UserProfile%_bazel_%UserName%フォルダ(例えばC:\Users\Kurozumi_bazel_Kurozumi)に作成されます。ファイルのサイズも20GBくらいあるので、不要であれば、このフォルダを削除しても問題ありません。
また、ビルドに使用したPythonの仮想環境も不要であれば削除できます。

実行環境にTensorFlow 2.2.0-rc0を導入する方法

新たなPythonの仮想環境に、上記でビルドしたTensorFlowを導入する方法です。
以下は、tf2g:\venvs\tf2)という仮想環境にTensorFlowを導入する手順になります。

# 仮想環境を作成して有効化
python -m venv g:\venvs\tf2
g:\venvs\tf2\Scripts\activate.bat

# pipのアップデート(任意)
python -m pip install --upgrade pip

# ビルドしたTensorFlowのインストール
pip install g:\tensorflow_pkg\tensorflow-2.2.0rc0-cp38-cp38-win_amd64.whl
(tf2) G:\venvs\tf2>pip list
Package              Version
-------------------- ----------
absl-py              0.9.0
astunparse           1.6.3
cachetools           4.0.0
certifi              2019.11.28
chardet              3.0.4
gast                 0.3.3
google-auth          1.11.3
google-auth-oauthlib 0.4.1
google-pasta         0.2.0
grpcio               1.27.2
h5py                 2.10.0
idna                 2.9
Keras-Preprocessing  1.1.0
Markdown             3.2.1
numpy                1.18.1
oauthlib             3.1.0
opt-einsum           3.2.0
pip                  19.2.3
protobuf             3.11.3
pyasn1               0.4.8
pyasn1-modules       0.2.8
requests             2.23.0
requests-oauthlib    1.3.0
rsa                  4.0
scipy                1.4.1
setuptools           41.2.0
six                  1.14.0
tensorboard          2.1.1
tensorflow           2.2.0rc0
tensorflow-estimator 2.1.0
termcolor            1.1.0
urllib3              1.25.8
Werkzeug             1.0.0
wheel                0.34.2
wrapt                1.12.1

TensorFlowの導入後、以下のようなコマンドで簡単な動作確認を行えます。

python -c "import tensorflow as tf; print(tf.__version__); print(tf.keras.__version__)"
python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"
(tf2) G:\venvs\tf2>python -c "import tensorflow as tf; print(tf.__version__); print(tf.keras.__version__)"
2020-03-14 21:52:09.302412: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cudart64_102.dll
2.2.0-rc0
2.2.4-tf

(tf2) G:\venvs\tf2>python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"
2020-03-15 00:59:53.263998: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cudart64_102.dll
2020-03-15 00:59:54.376910: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library nvcuda.dll
2020-03-15 00:59:54.418526: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1561] Found device 0 with properties:
pciBusID: 0000:01:00.0 name: TITAN RTX computeCapability: 7.5
coreClock: 1.77GHz coreCount: 72 deviceMemorySize: 24.00GiB deviceMemoryBandwidth: 625.94GiB/s
2020-03-15 00:59:54.428573: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cudart64_102.dll
2020-03-15 00:59:54.475614: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cublas64_10.dll
2020-03-15 00:59:54.520113: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cufft64_10.dll
2020-03-15 00:59:54.548255: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library curand64_10.dll
2020-03-15 00:59:54.588417: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cusolver64_10.dll
2020-03-15 00:59:54.621950: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cusparse64_10.dll
2020-03-15 00:59:54.696526: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cudnn64_7.dll
2020-03-15 00:59:54.700714: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1703] Adding visible gpu devices: 0
2020-03-15 00:59:54.725085: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x2095abeaaa0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2020-03-15 00:59:54.730785: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): Host, Default Version
2020-03-15 00:59:54.735625: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1561] Found device 0 with properties:
pciBusID: 0000:01:00.0 name: TITAN RTX computeCapability: 7.5
coreClock: 1.77GHz coreCount: 72 deviceMemorySize: 24.00GiB deviceMemoryBandwidth: 625.94GiB/s
2020-03-15 00:59:54.742297: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cudart64_102.dll
2020-03-15 00:59:54.746846: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cublas64_10.dll
2020-03-15 00:59:54.750494: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cufft64_10.dll
2020-03-15 00:59:54.754141: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library curand64_10.dll
2020-03-15 00:59:54.757341: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cusolver64_10.dll
2020-03-15 00:59:54.760597: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cusparse64_10.dll
2020-03-15 00:59:54.766100: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cudnn64_7.dll
2020-03-15 00:59:54.770008: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1703] Adding visible gpu devices: 0
2020-03-15 00:59:55.836500: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1102] Device interconnect StreamExecutor with strength 1 edge matrix:
2020-03-15 00:59:55.840482: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1108]      0
2020-03-15 00:59:55.843205: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1121] 0:   N
2020-03-15 00:59:55.847318: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1247] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 19151 MB memory) -> physical GPU (device: 0, name: TITAN RTX, pci bus id: 0000:01:00.0, compute capability: 7.5)
2020-03-15 00:59:55.857952: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x20993641410 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:
2020-03-15 00:59:55.862773: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): TITAN RTX, Compute Capability 7.5
tf.Tensor(-292.83417, shape=(), dtype=float32)