WindowsでTensorFlow1.13.1（CUDA10.1+cuDNN7.5.0）をビルドしてインストールするまでの手順

Windows環境でGPU版のTensorFlow 1.13.1（CUDA 10.1 + cuDNN 7.5.0）をビルドしてインストールするまでのポイントを紹介します。
なお、細かい説明は省略しているので、詳細は[Blog](https://dev.infohub.cc/build-tf-1131-gpu/)も参照していただければと思います。

# 環境
- ハードウェア/OS
    - CPU: Intel Core i7-7700K
    - OS: Windows 10 Pro Build 17763 (64bit)
- TensorFlow関連
    - TensorFlow 1.13.1
    - CUDA 10.1 for Windows
    - cuDNN 7.5.0 for Windows（CUDA 10.1用）
- ビルド関連
    - Microsoft Visual C++ 2015 Redistributable Update 3
    - Microsoft Build Tools 2015 Update 3
    - MSYS2 x64
    - Bazel 0.19.0
    - Python 3.6.8（tf1.13.1はPython 3.7にも対応しているようです）

## 今回の作業で利用しているパスの情報

|内容|パス|
|:--|:--|
|MSYS2インストール先|C:\msys64|
|Bazelインストール先|C:\tools|
|Pythonインストール先|C:\Python36|
|TensorFlowビルド用Python環境|C:\envs\build_tf1131|
|TensorFlowビルドパス|C:\build\tf1131|
|TensorFlowを利用するPython環境|C:\envs\tf1131|


# ビルド環境の構築
## Visual C++ Build Tools 2015のインストール
1. Microsoft Visual C++ 2015 再頒布可能パッケージ Update 3（x64版）のインストール
2. Microsoft Build Tools 2015 Update 3のインストール

## MSYS2のセットアップ
1. 64bit版のMSYS2（msys2-x86_64-20180531.exe）を``C:\msys64``にインストール
2. 環境変数PATHに``C:\msys64\usr\bin``を追加
3. ``C:\msys64\msys2_shell.cmd``でコンソールを起動し``pacman -Syu``で更新
4. 再度コンソールを再起動し、``pacman -Su``、``pacman -S git patch unzip``でパッケージ追加


## Bazelのセットアップ
以下コマンドで``C:\tools``配下に、Bazel **0.19.0**をダウンロード。wgetでSSL関連のエラーが出る場合は、wgetのオプションに``--no-check-certificate``を追加。

```
cd /d c:\
mkdir tools
cd tools
wget https://github.com/bazelbuild/bazel/releases/download/0.19.0/bazel-0.19.0-windows-x86_64.exe -O bazel.exe
```
次の環境変数を設定。

| 環境変数名 | 設定値 |
|:--|:--|
| PATH  | C:\toolsを追加  |
| BAZEL_SH  | C:\msys64\usr\bin\bash.exe  |
| BAZEL_VC  | C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC |


## Python 3.6.8のセットアップ
- Python.orgのPython 3.6.8(x64)を``C:\Python36``にインストール
- 環境変数PATHに``C:\Python36\Scripts\``と``C:\Python36\``を追加（追加されていない場合のみ）

## CUDA 10.1、cuDNN 7.5.0のセットアップ
- CUDA 10.1をインストール
- cuDNN 7.5.0をインストール（zipファイルの中身を``C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1``フォルダに上書き）
- 環境変数PATHに以下のパスを追加

```
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\libnvvp
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\extras\CUPTI\lib64
```

## Windowsのロングパス名を有効化
- ファイル名を指定して実行で``gpedit.msc``を起動
- コンピューターの構成> 管理者用テンプレート> システム> ファイルシステム　を選択
- ``Win32の長いパスを有効にする``を``有効``に設定


# TensorFlow 1.13.1のビルド
スタートメニューから**Visual C++ 2015 x64 Native Build Tools Command Prompt**を起動して、以下のコマンドを実行。

```
mkdir c:\venvs
python -m venv c:\venvs\build_tf1131
C:\venvs\build_tf1131\Scripts\activate.bat

python -m pip install --upgrade pip

pip3 install six numpy wheel
pip3 install keras_applications==1.0.7 --no-deps
pip3 install keras_preprocessing==1.0.9 --no-deps


mkdir C:\build\tf1131
cd /d c:\build\tf1131

git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
git checkout v1.13.1

python ./configure.py
```
configure.pyで以下の値を設定します。（Enterキーでデフォルト値が利用されます）
CUDA CC versionと、optimization flagは利用しているGPUやCPUに合わせてバージョンを設定してください。

| 設定項目 | 設定値 |
|:--|:--|
|Location of python|c:\venvs\build_tf1131\Scripts\python.exe|
|Python Library path|c:\venvs\build_tf1131\lib\site-packages|
|XLA JIT support|N|
|ROCm support|N|
|CUDA support|Y|
|CUDA SDK version|10.1|
|CUDA location|C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.1|
|cuDNN version|7.5|
|cuDNN location|C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.1|
|CUDA CC version|7.5|
|optimization flags|/arch:AVX2|
|override eigen inline|Y|

上で利用したコンソールを利用し、以下コマンドでビルドを行います。（このタイミングでパーソナルファイアウォールを無効化しておかないと、パッケージのダウンロードに失敗する可能性があります）

```
bazel build --config=opt --copt=-nvcc_options=disable-warnings //tensorflow/tools/pip_package:build_pip_package --cpu=x64_windows --compiler=msvc-cl
```


# Wheelパッケージの作成
ビルドで利用したコンソールを引き続き利用し、以下コマンドでwheelパッケージを作成。

```
cd /d C:\build\tf1131\tensorflow
mkdir ..\out
.\bazel-bin\tensorflow\tools\pip_package\build_pip_package ..\out
```

おそらく**simple_console_for_windows.zipのファイルサイズが0バイトでエラーが発生**すると思われるので、以下の作業を行います。
1. ``C:\build\tf1131\tensorflow\bazel-out\x64_windows-opt\bin\tensorflow\tools\pip_package\simple_console_for_windows.zip``ファイルを削除
2. ``C:\build\tf1131\tensorflow\bazel-out\x64_windows-opt\bin\tensorflow\tools\pip_package\simple_console_for_windows.zip-0.params``ファイルをテキストエディタで開き、正規表現で``^.+\.zip\n``の行（～.zipになっている行）を全て削除
3. コンソールに以下コマンドを入力し、再度wheelパッケージを作成

```
cd /d c:\build\tf1131\tensorflow\bazel-tensorflow
.\external\bazel_tools\tools\zip\zipper\zipper.exe vcC bazel-out/x64_windows-opt/bin/tensorflow/tools/pip_package/simple_console_for_windows.zip @bazel-out/x64_windows-opt/bin/tensorflow/tools/pip_package/simple_console_for_windows.zip-0.params

cd /d c:\build\tf1131\tensorflow
.\bazel-bin\tensorflow\tools\pip_package\build_pip_package ..\out
```

これで、``C:\build\tf1131\out``フォルダに``tensorflow-1.13.1-cp36-cp36m-win_amd64.whl``が作成されます。


# ビルドしたTensorFlow 1.13.1の導入
## CUDA 10.1用の対応
CUDA 10.1はdllファイル名のバージョン番号が統一されていないため、そのままではTensorFlow利用時にdllファイルが見つからずにエラーになる場合があります。（TensorFlowは、CUDA 10.1の場合cublas64_101.dllのように、ファイル名の最後が``101``のファイルをロードしようとします。しかし、CUDA 10.1に含まれるファイルには、*_10.dllと*_101.dllが混在した状態になっています）

ここでは、**シンボリックリンク**を使って、CUDA10.1のネーミングルールに合わせたファイルを作成するため、コマンドプロンプトを**管理者モード**で起動し、以下コマンドを実行します。

```
cd /d "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin\"

mklink cublas64_101.dll   cublas64_10.dll
mklink cublasLt64_101.dll cublasLt64_10.dll
mklink cufft64_101.dll    cufft64_10.dll
mklink cufftw64_101.dll   cufftw64_10.dll
mklink curand64_101.dll   curand64_10.dll
mklink cusolver64_101.dll cusolver64_10.dll
mklink cusparse64_101.dll cusparse64_10.dll
mklink nppc64_101.dll     nppc64_10.dll
mklink nppial64_101.dll   nppial64_10.dll
mklink nppicc64_101.dll   nppicc64_10.dll
mklink nppicom64_101.dll  nppicom64_10.dll
mklink nppidei64_101.dll  nppidei64_10.dll
mklink nppif64_101.dll    nppif64_10.dll
mklink nppig64_101.dll    nppig64_10.dll
mklink nppim64_101.dll    nppim64_10.dll
mklink nppist64_101.dll   nppist64_10.dll
mklink nppisu64_101.dll   nppisu64_10.dll
mklink nppitc64_101.dll   nppitc64_10.dll
mklink npps64_101.dll     npps64_10.dll
mklink nvblas64_101.dll   nvblas64_10.dll
mklink nvgraph64_101.dll  nvgraph64_10.dll
```

## TensorFlow 1.13.1のインストール
以下コマンドで、ビルドしたTensorFlow 1.13.1をインストールできます。

```
python -m venv C:\venvs\tf1131
C:\venvs\tf1131\Scripts\activate.bat
python -m pip install --upgrade pip

pip3 install C:\build\tf1131\out\tensorflow-1.13.1-cp36-cp36m-win_amd64.whl
```

## 動作確認
パッケージ一覧

```
pip3 list
Package             Version
------------------- -------
absl-py              0.7.0
astor                0.7.1
gast                 0.2.2
grpcio               1.19.0
h5py                 2.9.0
Keras-Applications   1.0.7
Keras-Preprocessing  1.0.9
Markdown             3.0.1
mock                 2.0.0
numpy                1.16.2
pbr                  5.1.2
pip                  19.0.3
protobuf             3.6.1
setuptools           40.6.2
six                  1.12.0
tensorboard          1.13.0
tensorflow           1.13.1
tensorflow-estimator 1.13.0
termcolor            1.1.0
Werkzeug             0.14.1
wheel                0.33.1
```

簡単な動作確認

```
python -c "import tensorflow as tf; tf.enable_eager_execution(); print(tf.reduce_sum(tf.random_normal([1000, 1000])))"
```