tensorflowをコンパイルしてインストール

#背景

全体的に、そんなに詳しくないので、アドバイス募集中です。

この問題は、
> bazelのバージョン指定に矛盾発覚。
> 3.99.0より低いバージョンで無いとtensorflowコンパイルできないとエラー出すのに、
> 4.7.2より高いバージョンで無いとtensorflowコンパイルできないとか言われる…。

どうもタイミングによって、c:\tensorflow\configure.pyの内容が変わり、
> _TF_MIN_BAZEL_VERSION = '4.2.2'
> _TF_MAX_BAZEL_VERSION = '5.99.0'

と書いてあるか、
> _TF_MIN_BAZEL_VERSION = '3.7.2'
> _TF_MAX_BAZEL_VERSION = '3.99.0'

と書いてあるか変わる。ガチャですか？

元はtensorflowのコンパイルを計画していた訳ではなく、途中経過として、コンパイルまでで掲載する事にした。
本来は、XLA_GPUと、GPUを使いたかったのだが、まだ果たせず。
最終的に、CUDAはcuda_11.5.2_496.13_windowsであり、cuDNNはcudnn-windows-x86_64-8.3.2.44_cuda11.5-archiveの状態。

経緯としては、NVIDIA CUDA ツールキット 11系にしたかったが、11.0と11.1がダウンロードサイトから消えており、11.2にせざるを得なかった。同時に、cuDNNも8.1.1になる。
さらにそこでdeviceQuery.exeを実行した所、CUDA Driver Version 11.5でRuntime Version11.2と表示された為、
バージョンの不整合を疑い、CUDAを11.5.3、cuDNN8.3.2、tensorflowをR2.7にした。
おそらく、nVidiaのドライバーのバージョンが上がってしまった為に、不整合が起きたのだろう。
なお、cuDNN8.3系にはバグがあるらしく、8.2系もしくは8.1系にするか、ひと工夫必要になる。あとに書きますが。
さらにPythonディレクトリ下にゴミが残ってる可能性を疑い、3.9系にした。

#参考サイト
##tensorflow他バージョン決定の理由
https://www.tensorflow.org/install/source_windows

##コンパイル方法
https://qiita.com/kHz/items/6af115d04628ecc82c43

##nVidiaによるcuDNNインストール方法
https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#installwindows

## tensorflowのリビジョン調査
https://github.com/tensorflow/tensorflow/branches/all

## グラフィックボードごとの、数値調査
https://developer.nvidia.com/cuda-gpus

## コンパイルエラーの解決
https://githubmemory.com/repo/google/ruy/issues/263


#インストール手順

##pythonのインストール

Windows x86-64 executable installer、この場合は下記をダウンロードして入れる。
``python-3.9.10-amd64exe``

インストールする時は、初期画面で全てのチェックボックスをチェックしないとはまります。
「Customize installation」選んでインストールした方が良さそう。

「Install launcher for all users (recommended)」指定。
「Add Python 3.9 to PATH」指定。
カスタム。
「py launchr」指定。よくわかりませんが。
「Install for all users」指定しておいた方が、その後のPathの扱いなどが楽。
「Disable path length limit」表示されたらクリックしてパス長の制限を解除。

Pathに、下記があればOK。
```C:\Program Files\Python39\Scripts\```
```C:\Program Files\Python39\```

バージョン確認。
```python --version```


##番外編、プロキシ環境でのセットアップ

プロキシ認証のせいでこのままだと動かない。どこかファイルに設定する解決法がある筈だが(実際、１台のPCは何もしていない)。
これを打っても出てこなかった。
```pip config -v list```

結局わからなかった為に、同じコマンドプロンプトで下記実施。

```set HTTP_PROXY=http://アカウント:パスワード@プロキシURL:ポート```
```set HTTPS_PROXY=http://アカウント:パスワード@プロキシURL:ポート```

ちなみに、set HTTPS_PROXY=http://、についてはhttpsの打ち間違いでは無くてhttpです。

なお、パスワードで記号を使っている場合は、例えば@なら%40などの回避が必要。昨今、パスワードの強度から記号が必須な事が多いが、こういう場合は極めて面倒臭い…。

##Visual Studio C++ビルドツールを入れる
###Visual Studioのダウンロードサイトから以下をダウンロード&インストールする
両方入れないとうまくいかないらしい。
再起動を要求されることあり、いや、再起動した方が無難。
```Visual Studio 2019 の Microsoft Visual C++ 再頒布可能パッケージ```
```Build Tools for Visual Studio 2019```


##CUDA(NVIDIAグラフィックスドライバ)のインストール

NVIDIAグラフィックスドライバ

https://www.nvidia.co.jp/drivers

から、セットアップするPCに該当するドライバをダウンロード、インストール。
おそらく再起動を要求される。

##CUDAインストール

https://developer.nvidia.com/cuda-toolkit-archive

「Windows」「X86_64」「10」(おそらくWindows10)「exe(local)」選択。

ここでは、NVIDIA CUDA ツールキット 11.5.3を入れる。
```cuda_11.5.2_496.13_windows.exe```

PATH、CUDA_PATHにインストールしたCUDAのフォルダが含まれている事を確認。

##cuDNNのインストール

CUDAのバージョンに対応するcuDNNを落として入れる。

https://developer.nvidia.com/rdp/cudnn-archive

ここでは8.3.2。
``cudnn-windows-x86_64-8.3.2.44_cuda11.5-archive.zip``

ダウンロードした .zip ファイルを解凍し、「cuda」フォルダ下に展開された全フォルダとファイルを、先ほどCUDA ツールキットをインストールしたディレクトリ(C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.5\)にコピーする。

##zlibのインストール
nVidiaのページに書いてあるのだが、zlibなるものを入れる必要があるらしい。入れないと、学習など実行時に下記のエラーが出る。

``Could not load library cudnn_cnn_infer64_8.dll. Error code 126
Please make sure cudnn_cnn_infer64_8.dll is in your library path!``

対処としては、cuDNNを8.1系にするか8.2系にするか、という対処法もある模様だが、
nVidiaのページにzlib入れろと書いてあるのでそちらを採用。
下記ページの「3.1.3. Installing zlib」に「Download and extract the zlib package from ZLIB DLL.」とあるので、「ZLIB DLL」にカーソルを合わせて、「名前を付けてリンク先を保存」する。

https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-zlib-windows

``zlib123dllx64.zip``
がダウンロードされるので、解凍してzlib123dllx64 -> dll_x64 と辿って、下記をパスの通ったディレクトリに入れる。
``zlibwapi.dll``

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.5\bin 、で良いと思います。

##deviceQuery.exeのビルド
直接は関係ないが、動作確認の為にdeviceQuery.exeをビルドしておいた方が良い。
「C:\ProgramData\NVIDIA Corporation\CUDA Samples\v11.5\1_Utilities\deviceQuery」
にある、「deviceQuery_vs2019.sln」をVisual Studio 2019 (コミュニティ版で良い)で開き、
「deviceQuery」を右クリック -> ビルド、で、「deviceQuery.exe」が「C:\ProgramData\NVIDIA Corporation\CUDA Samples\v11.5\bin\win64\Debug」に作られる。

## MSYS2インストール
Windowsで基本的なLinuxコマンドを使えるようになる、らしい。

MSYS2の公式サイトからダウンロード&インストールする。

MSYS2の動作環境を整える。上手くいかないのでWindowsメニューから普通にMSYS2を起動した。

MSYS2を管理者権限で起動し、pacmanのパッケージを一括アップグレードする
(-Sy: 最新のパッケージデータベースをダウンロードする）
-Su: インストールしたパッケージをアップグレードする）
以下、全てMSYS2で実行。
```pacman -Syu```

MSYS2を再起動して以下のコマンドを実行する （[Y]でインストールを完了）
```pacman -Su```
```pacman -S git patch unzip zip ed```


MYSYS2の文字コードを変更しておかないと、後でエラーメッセージに苦しむことになる。
端末上で「右クリック」→「Options...」→「Text」の「locale」を「ja_JP」、「Character set」を「SJIS」


Windows側のPATHを読み込めるようにする
Windowsの システムのプロパティ＞詳細設定＞環境変数 にて、以下を[新規]で追加する。
```変数 MSYS2_PATH_TYPE```
```値 inherit```

同時に下記を実施。

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

##Bazelインストール

bazel.exeをダウンロードするディレクトリを作成し、wgetで取得する。

下記URLを見て、今回入れようとしているtensorflowのバージョンが2.7系になって、Tensorflowのページにもまだ記載が無いのだが、安全に振ってR2.6系同様に、bazelは3.7.2とし、configure.pyに
> _TF_MIN_BAZEL_VERSION = '4.2.2'

と書いてあったら、c:\bazelと、c:\tensorflowを削除してここまで戻る。

https://www.tensorflow.org/install/source_windows?hl=ja

最後の--no-check-certificateは、カスペルスキー入れてるが故に必要だった。

```cd /c/```
```mkdir bazel```
```cd bazel/```
```wget https://github.com/bazelbuild/bazel/releases/download/3.7.2/bazel-3.7.2-windows-x86_64.exe -O bazel.exe --no-check-certificate```

## Pythonの各種パッケージインストール

トラブルの元になるので、既存のtensorflow環境を壊しても良ければだがアンインストールする。
なお、アンインストールしなくても、バージョンの不整合が発生すると思われる。
```python -m pip uninstall -y tensorflow tensorflow-cpu tensorflow-gpu tf-models-official tensorflow_datasets tensorflow-hub keras tensorflow-text tensorboard```

pipでインストールする
```pip install pip six numpy wheel mock```
```pip install keras_applications```
```pip install keras_preprocessing```

なお、numpyのバージョンについては、ここまでバージョンを上げると、むしろ新しいバージョンが必要になる模様。

他に、過去に下記を実施している。
```python -m pip install -U matlablib```
```python -m pip install scipy```
```python -m pip install opencv-python```

追記、下記実行した形跡があった。
```pip install sklearn.svm```
```pip install scikit-learn```

##TensorFlowをダウンロードし、コンフィグの設定をする

###Bazelのパスを通す
```export PATH=/c/bazel:$PATH```

下記も実施した、ただし、必要かどうかは不明。Progra~2にした理由は、どうもProgram Files (x86)の記載が悪さしている疑いがあったから。MIB055~1はMicrosoft Visual Studioの略です。NVIDIA~2はNVIDIA GPU Computing Toolkitの略です。
下記コマンドで、8.3形式のフォルダ名は調査可能。
```dir /x```

他に、システムの環境変数に既に下記が設定されていた場合、システムの環境変数が優先される模様。
整合性に注意(それでハマりました)。

```set BAZEL_VS=C:\Progra~2\MIB055~1\2019\Community```
```set BAZEL_VC=C:\Progra~2\MIB055~1\2019\Community\VC```
```set BAZEL_VC_FULL_VERSION=14.29.30133```
```set BAZEL_WINSDK_FULL_VERSION=10.0.13862.0```

``export PATH=C:\Progra~1\NVIDIA~2\CUDA\v11.5\bin:$PATH``
``export PATH=C:\Progra~1\NVIDIA~2\CUDA\v11.5\extras\CUPTI\lib64:$PATH``
``export PATH=C:\Progra~1\NVIDIA~2\CUDA\v11.5\include:$PATH``

###TensorFlowのGitリポジトリを取得する
```cd /c/```
```git clone https://github.com/tensorflow/tensorflow.git```
```cd tensorflow/```

この後チェックアウトが入るが、リビジョンは下から適当に選択。

https://github.com/tensorflow/tensorflow/branches/all

チェックアウト。なお、r2.7の「r」をつけ忘れると見つからない。
```git checkout r2.7```

###コンフィグ
```python configure.py```

ただし、ここで、4.2.2まで上げろとのエラーが出る場合は、
C:\tensorflow\configure.py
の中に、
> _TF_MIN_BAZEL_VERSION = '4.2.2'
> _TF_MAX_BAZEL_VERSION = '5.99.0'

と書いてある可能性が高いので、c:\bazel及び、c:\tensorflowを削除して、Bazelインストールまで戻る
ガチャですか？

特にエラーが出なかった場合は、いくつか質問されるのでYやNなどを入力していく。

```Please specify the location of python. [Default is C:\Program Files\Python39\python.exe]:```
どうも「Program Files」の指定が悪さするので、「Progra~1」にして下記入力。
```C:\Progra~1\Python39\python.exe```

```Found possible Python library paths: C:\Program Files\Python39\lib\site-packages```
```Please input the desired Python library path to use.  Default is [C:\Program Files\Python39\lib\site-packages]```
同上。
```C:\Progra~1\Python39\lib\site-packages```

```Do you wissh to build TensorFlow with ROCm support？```
CUDAをYにするならここは絶対にN。
```N```

```Do you wieh to build TensorFlow with CUDA support？```
CUDA使いたいのでY。
```Y```

```Please note that each additioinal compute capability signigficantly increases your buid time and binari size, and that TensoFlow only supports compute capabilities >= 3.5 ```
下記を見て決める。

https://developer.nvidia.com/cuda-gpus

私はGeForce 1080Tiなので6.1。
```3.5,6.1```

```Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is /arch:AVX]: ```
ここでおそらくtensorflow v2を指定するのだと思う。
```/arch:AVX2```


```Woud you like to override eigen storong inline for some C++ compilatoin to reduce the complaton time？```
よくわからないがY
```Y```

```Would you like to nteractively configure ./WORKSPACE for Android builds？```
Android使わないのでN
```N```

##BazelでTensorFlowビルドファイルを生成する
###whlファイルを生成するディレクトリを作成した後、ビルドするディレクトリに移動する
```cd /c/```
```mkdir tmp```
```cd /c/tensorflow/```

###ビルドファイル生成前のビルド

オプションの類は、下記から持ってきた。

https://tensorflow.google.cn/install/source_windows?hl=ja

加えて、

https://github.com/keras-team/keras/blob/master/.bazelrc

ビルドコマンド。最終的に、Googleのページを採用。CUDAに関して二重指定だよとエラーが出る。
``bazel build --config=opt --config=cuda --define=no_tensorflow_py_deps=true //tensorflow/tools/pip_package:build_pip_package``

他に、下記オプションという説もある。
```bazel build --config=opt --config=cuda --define=tensorflow_enable_mlir_generated_gpu_kernels=0 --define=no_tensorflow_py_deps=true //tensorflow/tools/pip_package:build_pip_package```

```bazel build --config=opt --define=tensorflow_enable_mlir_generated_gpu_kernels=0 --define=no_tensorflow_py_deps=true //tensorflow/tools/pip_package:build_pip_package```

```bazel build --config=opt --config=cuda --config=xla  --config=gdr --config=v2 --define=no_tensorflow_py_deps=true //tensorflow/tools/pip_package:build_pip_package```

ただし、この段階で、下記エラーに悩まされる事がある。どうも1回目のビルドで、ダウンロードしてくるか生成するファイルに問題がある模様。

```external/ruy/ruy/block_map.cc(334): error C2059: 構文エラー: ')'```
```111external/ruy/ruy/block_map.cc(334): error C2676: 二項演算子 '==': 'const ruy::CpuCacheParams' は、この演算子または定義済の演算子に適切な型への変換の定義を行いません。(新しい動作; ヘルプを参照)```

その場合は、下記ディレクトリの、
```C:\tensorflow\bazel-tensorflow\external\ruy\ruy```
「block_map.cc」の334～335の改行を消し、cpu_cache_paramsの前の余分な空白を削除した。

こちらの方に感謝。

https://githubmemory.com/repo/google/ruy/issues/263

他に、下記ファイルに関するエラーがでる事もある。
``tensorflow/lite/python/analyzer_wrapper/model_analyzer.cc(166): ``

その時は、「model_analyzer.cc」の166行目近辺の改行を削除し余計な空白を削除し、シングルクオート「'」がなぜかASCII文字でない為、半角の「'」に変更して、
最終的に下記の様な行にする。
```  out_stream << "Your TFLite model has '" << subgraphs->Length() << "' subgraph(s). In the subgraph description below,\nT# represents the Tensor numbers. ";```

この程度の修正ができないと、tensorflowのソースからのビルドはしてはいけません、という事だろうか？

ここで、再度、ビルドコマンド投入。長時間かかる。手元の環境で4時間かかった。
``bazel build --config=opt --config=cuda --define=no_tensorflow_py_deps=true //tensorflow/tools/pip_package:build_pip_package``

###ビルドを実行する。
長時間かかると聞いていたがそんなに掛からなかった。20分程度。何か間違えたか？
```bash bazel-bin/tensorflow/tools/pip_package/build_pip_package /c/tmp/tensorflow_pkg```

###ビルドファイル、すなわちtensorflowインストール
```cd /c/tmp/tensorflow_pkg```
```pip install tensorflow-2.7.1-cp39-cp39-win_amd64.whl```

###確認。
```python -c "import tensorflow as tf; print( tf.__version__ )"```
```python -c "from tensorflow.python.client import device_lib; print(device_lib.list_local_devices())"```
期待としては、ここでXLA_GPUが表示される事だったのだが、出てこなかった。