ROCm 1.8.2 で TensorFlow upstream(1.9.0-rc0)をコンパイルする試み(CIFAR10 11500 examples/sec @ VEGA56 80W. 2018 年 7 月 22 日時点)

2019 年 7 月 16 日追記: 最近では `pip install tensorflow-rocm` が十分動くので, 単に TensorFlow を ROCm で使いたい場合は pip を使いましょう.

--------------------------------

漢なら ROCm で TensorFlow 動かしたいですよね!

チャレンジしましょう!

2018 年 9 月 23 日追記: 昨今では TensorFlow 1.9 あたりから prebuilt 版が出てきて pip とかでインストールできるようになりました. まずは ROCm で TensorFlow 試したい場合は prebuilt 版をおすすめします.

https://github.com/ROCmSoftwarePlatform/tensorflow-upstream

2018 年 9 月 23 日時点では ROCm 1.9 + TensorFlow 1.10 が最新です.


2018 年 7 月 21 日時点では, AMD ROCm オフィシャルで配布されているのは TensorFlow 1.3 になります.
これではちょと古いですよね..

`tensorflow-upstream` repo がありますのでこれをビルドします.

https://github.com/ROCmSoftwarePlatform/tensorflow-upstream

ROCm でのビルドのドキュメントなどが `tensorflow-upstream/rocm_docs` にありますので参考にしましょう.

* ROCm 1.8.2

ROCm は, 元来 PCI Gen3 以降のアーキティクチャ対応だったのですが, 仮想通貨マイナーのことも考慮してか, PCI Gen2 でも動くようになりました.
(いつのまにか FirePro W9100(Hawaii) あたりの古い GPU も非推奨ですが動作する GPU になっていました)

ただ, こちらで SandyBridge マシンにインストールしようとしたら, tensorflow ビルド時に nasm が illegal instruction で落ちるなどしました. こちらについては `tensorflow-upstream` の `configure` を少し書き換えればとりあえずは解決します(後述の解説を参照ください)

## 構成

* Ubuntu 16.04
* Python 3.5 (conda)
* ROCm 1.8.2
* そこそこ最新のアーキテクチャ(ROCm のページにあるサポート対象アーキテクチャ)の CPU
* RX 580(gfx803), VEGA(gtx900)
* Bazel

## 参考情報

参考になります, ありがとうございます.

深層学習で学習やるならNVIDIA一択？いや、AMDという選択肢がありますよ
https://qiita.com/kz_lil_fox/items/d1a18f58e9e5033e7e14

AMD製GPU + ROCm + OpenCV + TensorFlow でGPUコンピューティング環境をつくる
https://qiita.com/hktm/items/ead2ed4ed3441fca7311

## セットアップ

ROCm のサイトを参考に, ROCm をまずはインストールしておきます.

https://github.com/RadeonOpenCompute/ROCm
(`apt-get install rocm-dev` あたりまで)
 
blas など入れます.

```bash
$ sudo apt install rocrand rocfft rocblas
```

MIOpen を入れます(cuDNN みたいな計算アクセラレーションライブラリっぽい)

http://rocm-documentation.readthedocs.io/en/latest/Deep_learning/Deep-learning.html

```bash
$ sudo apt install miopen-hip miopengemm
```

python 3.5 環境を用意します(3.6 でも動くかも)
今回は (mini)conda を使いました.
 
```
$ conda create -n py35 python=3.5
$ source activate py35
```

numpy, six を入れます(他, python module 周りでビルドに失敗したら適宜パッケージを入れてください)

```
(py35) $ (pip install numpy six
```

Bazel をインストールしておきます.

tensorflow-upstream の branch は `develop-upstream` であることを確認しておきます.

configure します.

### optional

`tensorflow-upstream` では, 最適化オプションは `-march=haswell` がデフォルトになっており, これを configure で変えても他のところで `-march=haswell` を使っているところがあるため, 一部 CPU では動作しません(マイナー御用達の Celeron でも, たとえば G3930 など haswell 以降のアーキテクチャでも CPU 機能が一部かけているためか NG になります). 具体的には, tensorflow をビルドするために必要な依存プログラムの `protoc` や `nasm` あたりが, 実行時に Illegal instruction で落ちてしまいます.

(2018 年 9 月 23 日追記) この問題に対するパッチは https://github.com/ROCmSoftwarePlatform/tensorflow-upstream/pull/81 で取り込まれて修正されています.

以下のように, `configure.py` で, `-march=native`, `--host_copt=-march=native` に変更しておくとよいでしょう.


```diff
diff --git a/configure.py b/configure.py
index fc33325..45971da 100644
--- a/configure.py
+++ b/configure.py
@@ -486,7 +486,7 @@ def set_cc_opt_flags(environ_cp):
   elif is_windows():
     default_cc_opt_flags = '/arch:AVX'
   else:
-    default_cc_opt_flags = '-march=haswell'
+    default_cc_opt_flags = '-march=native'
   question = ('Please specify optimization flags to use during compilation when'
               ' bazel option "--config=opt" is specified [Default is %s]: '
              ) % default_cc_opt_flags
@@ -496,7 +496,7 @@ def set_cc_opt_flags(environ_cp):
     write_to_bazelrc('build:opt --copt=%s' % opt)
   # It should be safe on the same build host.
   if not is_ppc64le() and not is_windows():
-    write_to_bazelrc('build:opt --host_copt=-march=haswell')
+    write_to_bazelrc('build:opt --host_copt=-march=native')
   write_to_bazelrc('build:opt --define with_default_optimizations=true')
```

すでに他で tensorflow をビルドしている場合は, `$HOME/.cache/bazel` あたりのキャッシュファイルを消して, 以下の configure を走らせると確実そうです.

configure を走らせ, 初期設定をします.
だいたいデフォルト通りですが, 変更したところとしては XLA JIT を n にしました(Y でも動くとは思います).

```
$ 
$ ./configure
You have bazel 0.15.2 installed.
Please specify the location of python. [Default is /home/syoyo/miniconda3/envs/py35/bin/python]: 


Found possible Python library paths:
  /home/syoyo/miniconda3/envs/py35/lib/python3.5/site-packages
Please input the desired Python library path to use.  Default is [/home/syoyo/miniconda3/envs/py35/lib/python3.5/site-packages]

Do you wish to build TensorFlow with jemalloc as malloc support? [Y/n]: Y
jemalloc as malloc support will be enabled for TensorFlow.

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

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

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

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

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 GDR support? [y/N]: N
No GDR support will be enabled for TensorFlow.

Do you wish to build TensorFlow with VERBS support? [y/N]: N
No VERBS 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]: Y
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.

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

Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native]: 


Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: N
Not configuring the WORKSPACE for Android builds.
```

`build_python3` スクリプトを使ってビルドします.

```
(py35) $ ./build_python3
```

`build_python3` スクリプトの最後にある pip wheel のインストールで permission エラーが出る場合は, `--user` あたりでインストールしておきます.

```
(py35) $ pip3 install --user /tmp/tensorflow_pkg/tensorflow-1.9.0rc0-cp35-cp35m-linux_x86_64.whl
```

## 動作確認

Using GPUs
https://www.tensorflow.org/guide/using_gpu

で簡単な加算プログラムを動かしてみます.

```
2018-07-21 22:05:25.506635: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX512F
2018-07-21 22:05:25.507760: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1500] Found device 0 with properties: 
name: Device 67df
AMDGPU ISA: gfx803
memoryClockRate (GHz) 1.35
pciBusID 0000:65:00.0
Total memory: 8.00GiB
Free memory: 7.75GiB
2018-07-21 22:05:25.507806: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1611] Adding visible gpu devices: 0
2018-07-21 22:05:25.507838: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1031] Device interconnect StreamExecutor with strength 1 edge matrix:
2018-07-21 22:05:25.507854: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1037]      0 
2018-07-21 22:05:25.507870: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1050] 0:   N 
2018-07-21 22:05:25.507938: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1168] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 7539 MB memory) -> physical GPU (device: 0, name: Device 67df, pci bus id: 0000:65:00.0)
2018-07-21 22:05:25.523000: E tensorflow/core/common_runtime/gpu/gpu_device.cc:264] Illegal GPUOptions.experimental.num_dev_to_dev_copy_streams=0 set to 1 instead.
Device mapping:
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: Device 67df, pci bus id: 0000:65:00.0
2018-07-21 22:05:26.074124: I tensorflow/core/common_runtime/direct_session.cc:288] Device mapping:
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: Device 67df, pci bus id: 0000:65:00.0

MatMul: (MatMul): /job:localhost/replica:0/task:0/device:GPU:0
2018-07-21 22:05:26.075049: I tensorflow/core/common_runtime/placer.cc:935] MatMul: (MatMul)/job:localhost/replica:0/task:0/device:GPU:0
a: (Const): /job:localhost/replica:0/task:0/device:GPU:0
2018-07-21 22:05:26.075094: I tensorflow/core/common_runtime/placer.cc:935] a: (Const)/job:localhost/replica:0/task:0/device:GPU:0
b: (Const): /job:localhost/replica:0/task:0/device:GPU:0
2018-07-21 22:05:26.075117: I tensorflow/core/common_runtime/placer.cc:935] b: (Const)/job:localhost/replica:0/task:0/device:GPU:0
[[22. 28.]
 [49. 64.]]
```

Voila~! なんか experimental のエラーがでていますが, 動作はしました!

## CIFAR10

CIFAR10 を学習させてみます.
rocm-smi でクロックを下げていますが, VEGA56 で 80W で 11500 examples/sec でました.

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">ねんがんの ROCm tensorflow-upstream での CIFAR10 学習に成功したぞ!!!! ㊗️㊗️㊗️㊗️㊗️㊗️㊗️🎉🎉🎉🎉🎉🎉🎉💯💯💯💯💮💮💮😆😆😆😆💪💪💪💪🙏🙏🙏😤😤 VEGA56 setsclk 3 で 80W で 1150 examples/sec でました. ありがとうございます. <a href="https://t.co/lpNfF5FDWE">pic.twitter.com/lpNfF5FDWE</a></p>&mdash; Syoyo Fujita (@syoyo) <a href="https://twitter.com/syoyo/status/1020959255195615237?ref_src=twsrc%5Etfw">July 22, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

tf1.8 で 125W powerlimit な 1080 Ti で 10500 ~ 11500 examples/sec でした.

http://blog.gpueater.com/en/2018/04/23/00011_tech_cifar10_bench_on_tf13/

と比べても VEGA は NV GPU と同等くらいの性能が出ているので, メモリ容量すくない(VEGA56 は 8GB, 1080 Ti は 11 GB)という問題はありますが, コスパよさそうです. (CIFAR10 が動いたので, 少なくとも CNN あたりを含む学習はこれで問題なく AMD GPU で動くはず)

## 問題点

`import tensorflow` がめちゃくちゃ重くてつらい...(5,6 秒くらいかかる). どこかのモジュールがデバッグビルドになっているのかしら?


## ビルド失敗例

hipcc の設定(or clang のインストール?)がうまくいっていないと, hipcc が `nvcc`(CUDA) を呼び出すようになりビルドに失敗するケースがあります.
(環境変数に hcc を設定しても, bazel での環境ではなにやら書き換えられて nvcc になる.)

たとえば以下のような issue があります.

https://github.com/RadeonOpenCompute/ROCm/issues/148

これについてはよくわかりません. 遭遇したらなにかしらキャッシュをクリアするなりパッケージを再インストールするしかなさそうです.

## TODO

* CIFAR10 学習の精度を NVIDIA GPU と比較する.
* 仮想通貨マイニングプログラムとカーネルフージョンし, 機械学習しつつマイニングするスキームを確立したい.
* pytorch を ROCm でビルドする(ビルドオプションはあるが, 実際に動くかどうか)
* InfiniBand(VERBS) 有効にし, GPU クラスタで並列学習したい.
* **優秀な機械学習若人さまが, 優秀な ROCm 機械学習若人さまへと人類史上最速で昇華なされる**スキームを極める旅に出たい.