AIエッジコンテスト(実装コンテスト)のチュートリアル【3: Ultra96ボードのCPUで推論実行】

前回で学習環境を準備してCNNモデルを学習しました。次はコンテストの対象ボードであるUltra96にPYNQフレームワークを設定してPyTorchをインストールし、推論を実行してみましょう。とりあえず結果は出るので、コンテストに参加できますね！

### 環境
ホストPC：Ubuntu 16.04 LTS (Windows, MacユーザはVMWare, Parallel Desktop等の仮想環境をインストールして、その上にUbuntu 16.04 LTSをインストールしてください。Ubuntu18.04LTSでもできると思いますが、確認しておりません。)

### 用意するもの
+ PYNQ(v2.5)のイメージファイル
+ インターネットに接続できる環境の確認(有線LAN or Wifi)

### PYNQとは
PS上のPython でUltra96V2上のPLを制御することができるフレームワークです。OSはUbuntu18.04 LTS (PYNQv2.5)なので、学習と同じ環境で設計ができます。後日公開予定のハードウェアアクセラレーション編でもUbuntu上に設計ツールをインストールしますのでお勧めします。
Google Colabを使った学習と同様に、Ultra96V2での実行もJupyterNotebookで行うことができます。便利ですねぇ。

### PYNQのセットアップ
2.1 PYNQイメージの入手とセットアップ

PYNQの公式ドキュメント(https://ultra96-pynq.readthedocs.io/en/latest/) に従ってSDカードにPYNQイメージ(version 2.5)を焼いてください（ISOを直接SDカードにドラッグアンドドロップしてコピーする人がいますが、それではUltra96ボードを起動できません。。）

2.2 PYNQとホストPCの接続

PYNQドキュメント通りにホストPCとUltra96V2ボードが接続されていることを確認してください（下の図参考）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589480/3aa3bab0-e6af-eee2-a7a1-3c4911f996bc.png)

2.3 PyTorchのインストール（この作業は一度だけでよいです）

公式のPyTorchサイトではインストール方法が選べて大抵の環境ではコマンド一発でインストールできるのですが、運の悪いことにUltra96V2のビルド済みPyTorchがありません‥。面倒ですが、私がビルドしたPyTorchバイナリをUltra96に転送してインストールしましょう。そのため、Ultra96ボードをインターネットに接続して作業を行います。

2.3.1 Ultra96V2ボードをインターネットと接続
ライブラリをダウンロードするので、インターネットに接続します。2通りの方法があるので、どちらかの方法でインターネットと接続してください。

2.3.1.1 USB-LANコネクタを使う場合(LANケーブルとルータ等を準備してください)
Ultra96V2のUSBポートにUSB-LAN変換コネクタをそのまま繋げばインターネットに接続できます。 [たとえばこんなもの↓がAmazonで売ってます](https://www.amazon.co.jp/%E3%82%A8%E3%83%AC%E3%82%B3%E3%83%A0-%E6%9C%89%E7%B7%9ALAN%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC-Nintendo-%E3%82%AE%E3%82%AC%E3%83%93%E3%83%83%E3%83%88%E5%AF%BE%E5%BF%9C-EDC-GUA3A-B/dp/B07FD47QGV/ref=sr_1_11?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=USB-LAN&qid=1582652197&sr=8-11)。後述するWifi設定が面倒なら、金の力で解決しましょ（笑

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589480/e8823ec2-a5e1-f4a0-6dd0-f489b2353feb.png)

2.3.1.2 Wifiを使う場合(Wifiアクセスポイントを準備してください)

ホストPCのブラウザ(UbuntuはFirefoxがデフォルトでインストールされている)を起動して、URLに "http://192.168.3.1:9090" と入力してください。PYNQ上のJupyter Notebookにアクセスできます。

Jupyter Notebookの”/common/”をクリックしてWifiを設定するノートブック(wifi.ipynb)を起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589480/f71f5049-ecfd-f202-292e-476bfada7ba2.png)

ノートブック内にWifiの情報を入力してください。接続テストもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589480/87fabebe-df6c-5f6e-602e-1a02203c7cad.png)

2.3.2 SDカードのswap 領域を拡張

SSHコマンドを使ってUltra96V2上で作業を行います。ホストPCでTerminalを起動します。

```
(ホストPC) $ ssh xilinx@192.168.3.1
```
※パスワードを要求されるので”xilinx”を入力。
※ホストPCとUlra96V2で作業するのでTerminalを２つ起動しておくと捗ります。

インストール時にメモリを消耗するので, 以下のコマンドを実行してswap領域を拡張してください。

```
(Ultra96V2) $ swapon -s
(Ultra96V2) $ sudo dd if=/dev/zero of=/swap1 bs=1M count=2048
(Ultra96V2) $ sudo mkswap /swap1
(Ultra96V2) $ sudo vi /etc/fstab 
```

と入力して以下を追記。

```
/var/swap none swap sw 0 0
/swap1 swap swap
```

保存をして以下を実行。

```
(Ultra96V2) sudo swapoff /swap0
(Ultra96V2) $ sudo swapon /swap1
```

終わったら 

```
(Ultra96V2) # reboot
```

としてUltra96V2を再起動。

2.3.3 必要ライブラリをインストール
再起動したUltra96V2ボードにSSH接続して作業を行いましょう。

```
(ホストPC) $ ssh xilinx@192.168.3.1
```

以下のコマンドを実行して必要なライブラリをインストールします。`sudo su`コマンドを実行して管理者権限(プロンプトが「#」になる)で実行してください。

```
(Ultra96V2) # sudo su →パスワード(デフォルトはroot)を入力
(Ultra96V2) # apt-get install libopenblas-dev cython libatlas-base-dev m4 libblas-dev python3-dev cmake python3-yaml
```

2.3.4 ビルド済みPyTorchをダウンロード
以下にUltra96V2用のビルド済みPyTorch(1.4.0)と対応したTorchVisionを置いていますので、ホストPC上にダウンロードして、scpでUltra96V2に転送してください。
(Ultra96V2上で直接wgetを使ってダウンロードしてもOKです)

[torch-1.4.0a0+4bcf479-cp36-cp36m-linux_aarch64.whl](https://drive.google.com/file/d/1yRkKCxVyHVRkeKn53Kfws2yeDK01fRf8/view?usp=sharing)
[torchvision-0.5.0a0-cp36-cp36m-linux_aarch64.whl](https://drive.google.com/file/d/1OQ1WsCK0kH7vz8lp4E3B4LAcIPk_eK9V/view?usp=sharing)

ホストPCダウンロード先のディレクトリに移動した状態で以下を実行

```
$ scp torch-1.4.0a0+4bcf479-cp36-cp36m-linux_aarch64.whl xilinx@192.168.3.1:/home/xilinx
$ scp torchvision-0.5.0a0-cp36-cp36m-linux_aarch64.whl xilinx@192.168.3.1:/home/xilinx
```

2.3.5 PyTorchをインストール　
SSHでUltra96V2に接続してビルド済みPyTorchをインストールします。

```
(Ultra96V2) $ sudo pip3 install torch-1.4.0a0+4bcf479-cp36-cp36m-linux_aarch64.whl 
```

2.3.6 ビルド済みTorchVisionをインストール
同様にTorchVisionもインストールします。

```
(Ultra96V2) $ sudo pip3 install torchvision-0.5.0a0-cp36-cp36m-linux_aarch64.whl
```

2.4 サンプル推論プログラムをホストPCにダウンロード

[サンプル推論プログラム一式.zip](https://drive.google.com/file/d/1VCFYqdTS6H1oX6CTDmYk9VXoZd_7NARx/view?usp=sharing)をホストPCにダウンロードして、zipファイルのままUltra96V2に転送します。
※後日[githubにアップ](https://github.com/HirokiNakahara/FPGA_AI_Edge_Contest_2019)しておきました。

```
(ホストPCダウンロード先のディレクトリ) 
$ scp FPGA_AI_Edge_Contest_2019-master.zip xilinx@192.168.3.1:/home/xilinx
```

転送後, SSHで接続したUltra96V2上で解凍、ディレクトリ名を変更しておきます。

```
(Ultra96V2) $ unzip FPGA_AI_Edge_Contest_2019-master.zip
(Ultra96V2) $ mv FPGA_AI_Edge_Contest_2019-master FPGA_AI_Edge_Contest_2019
```

2.5 学習済みモデルをダウンロードしてホストに転送

手順1.6で生成された学習済みモデル(ここではyolov2_epoch20.pthとします)をUltra96V2に転送します。

ホストPCで学習済みモデルをダウンロードしたディレクトリ上で以下を実行。 

```
$ scp yolov2_epoch20.pth xilinx@192.168.3.1:/home/xilinx
```

デモを動かすため、Ultra9６V２とGoogle Colab上で学習に使ったディレクトリ構造を一致させます。

```
(Ultra96V2) $ cd /home/xilinx/FPGA_AI_Edge_Contest_2019/Training
(Ultra96V2) $ mkdir yolov2_alex_1
(Ultra96V2) $ mv /home/xilinx/yolov2_epoch20.pth yolov2_alex_1
```

2.6 推論を実行

[デモ用ノートブック(demo.ipynb)](https://drive.google.com/file/d/1Qmpr3TW3apqD_f2r2VA1USgjpa3PPAn2/view?usp=sharing)をホストPCにダウンロードしてください。scpコマンドでUltra96V2に転送します。

```
(ホストPCダウンロード先のディレクトリ) 
$ scp demo.ipynb xilinx@192.168.3.1:/home/xilinx/jupyter_notebooks
```

Ultra96V2に接続し、Jupyter Notebookを起動して demo.ipynb を実行して手順通りにノートブックを動かしてみてください。下のようになるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589480/eb5e4032-d5e1-a920-54b6-616623e83d99.png)


いかがでしたでしょうか。無事に推論できましたか？実行結果が保存されるので、scpを使ってホストPCに転送すれば少なくとも提出はできると思います。しかし、推論、遅いですねぇ。。

次はいよいよUltra96に乗っているFPGAを使ってハードウェアアクセラレータを作ってみましょう！