TinkerBoard で PlaidML を動かしてみた結果

* ねんがんの　Qiita の記事を　書いたぞ！
	* これで年末に何らかの Advent Calendar に参加できるぞ！	
<br>

* TinkerBoard で OpenCL が動くという見聞を得たため、
「じゃあ [**PlaidML**](https://github.com/plaidml/plaidml) も動くんじゃね？」ということで、試してみました。


## 準備

* OS には **Tinker OS (Debian) V2.0.7** をインストールしました。

~~~
$ sudo apt install opencl-headers clinfo
~~~

~~~
$ clinfo
Number of platforms                               0
~~~

なん…だと

~~~
$ sudo apt install ocl-icd-opencl-dev

$ clinfo
Number of platforms                               0
~~~

直らないですね…
<br>

* こんな情報が
	* [making clinfo work: fix /etc/OpenCL/venders -> **vendors**](https://tinkerboarding.co.uk/forum/archive/index.php/thread-1476.html)

	~~~
Please change the spelling of the file name
/etc/OpenCL/venders
to
/etc/OpenCL/vendors
~~~

* これは…ぜひ次回の Tinker OS release では fix して頂きたいところ。

~~~
$ cd /etc/OpenCL/
$ sudo ln -s venders vendors
~~~

~~~
$ clinfo
Number of platforms                               1
  Platform Name                                   ARM Platform
  Platform Vendor                                 ARM
  Platform Version                                OpenCL 1.2 v1.r9p0-05rel0-git(f980191).e4ba9e4c6ff8005348d0332aae160089
  Platform Profile                                FULL_PROFILE

...
~~~

* で、出たー！
<br>

* 引き続き、セットアップを続けます。

~~~
$ sudo apt install python3-venv python3-scipy python3-h5py python3-yaml
$ mkdir ~/venv
$ cd ~/venv/; python3 -m venv --system-site-packages plaidml
$ source ~/venv/plaidml/bin/activate
(plaidml) $ pip3 install -U pip
(plaidml) $ pip3 install -U plaidml-keras
(plaidml) $ pip3 list | grep plaidml
plaidml       0.3.0rc1   
plaidml-keras 0.3.4
~~~

* ありゃ？？  
インストールされた plaidml のバージョンがやけに古いです。
	* [PyPI: plaidml 0.3.0rc1](https://pypi.org/project/plaidml/0.3.0rc1/#files)
	* [PyPI: plaidml 0.3.4](https://pypi.org/project/plaidml/0.3.4/#files)
	* armv7l 向けの whl が無いのかあ…

### 試しに実行してみました

* ひとまず、plaidml 0.3.0rc1 でやってみました。

~~~
(plaidml) $ mkdir -p ~/_git/github/keras-team && cd $_/
(plaidml) $ git clone https://github.com/keras-team/keras.git
(plaidml) $ cd keras/
(plaidml) $ git checkout -b v2.0.8 refs/tags/2.0.8
(plaidml) $ cd examples/
~~~

~~~
(plaidml) examples$ time python3 mnist_mlp.py                                                                               
60000 train samples
10000 test samples
Traceback (most recent call last):
  File "mnist_mlp.py", line 41, in <module>
    model.add(Dense(512, activation='relu', input_shape=(784,)))
  File "/home/linaro/venv/plaidml/lib/python3.5/site-packages/keras/models.py", line 438, in add
    dtype=layer.dtype, name=layer.name + '_input')
  File "/home/linaro/venv/plaidml/lib/python3.5/site-packages/keras/engine/topology.py", line 1436, in Input
    input_tensor=tensor)
  File "/home/linaro/venv/plaidml/lib/python3.5/site-packages/keras/legacy/interfaces.py", line 87, in wrapper
    return func(*args, **kwargs)
  File "/home/linaro/venv/plaidml/lib/python3.5/site-packages/keras/engine/topology.py", line 1347, in __init__
    name=self.name)
  File "/home/linaro/venv/plaidml/lib/python3.5/site-packages/plaidml/keras/backend.py", line 1037, in placeholder
    dtype = ptile.convert_np_dtype_to_pml(dtype or floatx())
AttributeError: module 'plaidml.tile' has no attribute 'convert_np_dtype_to_pml'

real    0m4.594s
user    0m3.920s
sys     0m0.410s
~~~

* あかんか…

---

### 苦し紛れに

* bazel で plaidml をビルドするのは trial が長くなりそうなので、  
ダメ元で小手先でどうにかならないかやってみました。

~~~
$ mkdir -p ~/_git/github/plaidml && cd $_/
$ git clone https://github.com/plaidml/plaidml.git
$ cd ~/venv/plaidml/lib/python3.5/site-packages/plaidml/
$ gzip tile.py
$ cp ~/_git/github/plaidml/plaidml/plaidml/tile.py ./
$ cd keras/
$ gzip backend.py
$ cp ~/_git/github/plaidml/plaidml/plaidml/keras/backend.py ./
~~~

* そして再挑戦（事前に [mnist.npz](https://s3.amazonaws.com/img-datasets/mnist.npz) は準備済み）

~~~
(plaidml) examples$ time python3 mnist_mlp.py 
60000 train samples
10000 test samples
INFO:plaidml:b'Opening device "mali-t760.0"'
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 512)               401920    
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 512)               262656    
_________________________________________________________________
dropout_2 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 10)                5130      
=================================================================
Total params: 669,706
Trainable params: 669,706
Non-trainable params: 0
_________________________________________________________________
Train on 60000 samples, validate on 10000 samples
Epoch 1/1
60000/60000 [==============================] - 193s - loss: nan - acc: 0.0000e+00 - val_loss: nan - val_acc: 0.0000e+00
Test loss: nan
Test accuracy: 0.0

real    3m30.018s
user    0m28.490s
sys     0m4.220s
~~~

* **動きました！** loss は NaN ですが。
	* 実行時間は 1 epoch で **3 分 30 秒** 。  
	決して早くは無い値です。
	* 比較のために PC で以下の環境で確認したところ、  
	**18.3 秒** でした。
		* Keras v2.0.8
		* TensorFlow (CPU) v1.9.0
		* i5-4200U (2 core 4 thread)

* training 実行中も CPU 使用率は低いままです。
	* ヒートシンクは非常に熱くなっていました。

~~~
$ vmstat -S M 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0     99   1272      7    183    0    0    13    64  310  128  7  1 93  0  0
 0  0     99   1272      7    179    0    0     0    11 3048 1036  2  1 98  0  0
 0  0     99   1272      7    181    0    0     0     2 2989  902  2  0 98  0  0
 0  0     99   1272      7    181    0    0     0     2 3145 1160  2  1 96  0  0
 0  0     99   1272      7    181    0    0     0     0 3247 1202  2  1 97  0  0
 0  0     99   1272      7    181    0    0     0     1 3158 1168  3  1 97  0  0
 0  0     99   1271      7    181    0    0     0    13 3360 1250  3  1 96  0  0
~~~

## [Plaidbench](https://github.com/plaidml/plaidbench)

* MobileNet : **920** 秒で PASS

~~~
(plaidml) $ python3 plaidbench.py --plaid mobilenet

Running 1024 examples with mobilenet, batch size 1
INFO:plaidml:b'Opening device "mali-t760.0"'
Model loaded.
Compiling network...
Warming up ...
Main timing
Example finished, elapsed: 5.409723997116089 (compile), 920.5015776157379 (execution), 0.8989273218903691 (execution per example)
Correctness: PASS, max_error: 2.2292620997177437e-05, max_abs_error: 8.046627044677734e-07, fail_ratio: 0.0
~~~

* ResNet50 : **4549** 秒で PASS

~~~
(plaidml) $ python3 plaidbench.py --plaid resnet50

Running 1024 examples with resnet50, batch size 1
INFO:plaidml:b'Opening device "mali-t760.0"'
Model loaded.
Compiling network...
INFO:plaidml:b'Analyzing Ops: 61 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 134 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 186 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 283 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 329 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 432 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 524 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 616 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 719 of 810 operations complete'
INFO:plaidml:b'Analyzing Ops: 770 of 810 operations complete'
Warming up ...
Main timing
Example finished, elapsed: 33.58277153968811 (compile), 4549.551712751389 (execution), 4.442921594483778 (execution per example)
Correctness: PASS, max_error: 3.91797766496893e-06, max_abs_error: 2.086162567138672e-07, fail_ratio: 0.0
~~~

* Inception V3 : 動作せず

~~~
(plaidml) $ python3 plaidbench.py --plaid inception_v3

Running 1024 examples with inception_v3, batch size 1
array is too big; `arr.size * arr.dtype.itemsize` is larger than the maximum possible size.
Set --print-stacktraces to see the entire traceback
~~~

---

## 最後に

* 動いたのは動いたけど…loss は NaN、速度は亀クラスでした。
	* エッジデバイスなので training ではなく predict で評価しなければ。
	* 最新の PlaidML の armv7l 版をきちんと Bazel でビルドすれば  
	もっと良い結果になるかも？
		* [Arm aarch64 processor with Mali GPU support #39](https://github.com/plaidml/plaidml/issues/39)

* その他、アドバイス／マサカリなどありましたらぜひお願い申し上げます。

---

### 本記事を書くにあたって参考にさせて頂いた記事

* [[Keras/TensorFlow] 転移学習（Fine-tuning）](https://qiita.com/tshimba/items/60f7bcc8ae26b5004a3a)

* [plaidMLがいつの間にか色々素晴らしくなっていた件](https://qiita.com/Mco7777/items/7b33414bc113584493e9)

* [ASUS tinker boardのMali T764をOpenCV 3.3.1のOpenCLで酷使してみる](https://qiita.com/hon_no_mushi/items/e201890dcc78dc0d88f0)

* [TinkerBoardでOpenCLでMonacoinを採掘してみる](https://qiita.com/stnk20/items/43d9fd34fade338798b5)

* [[メモ] ASUS TinkerBoard: TinkerOS_Debian V2.0.7 関連](https://qiita.com/mt08/items/917af8b1df0f223a21af)

* [ラズパイ3よりもパワフルなTinkerboardを試す](https://qiita.com/tetsu_koba/items/6af74b2a842f3549f77c)

---

こちらからは以上になります。

---