Jetson Nano with Google Coral Edge TPU

# 追記 (2019/09/29)
September 2019 Updates (https://coral.withgoogle.com/news/updates-09-2019/ )によって、Jetson Nano上でも通常通りインストール可能となりました。

本記事の内容は不要です。
(今後、別のボードなどで似たような事象が発生する可能性があるので、記事自体は残させていただきます。)


## 追記 (2019/12/30)
必要なコマンドが、Get startedのページとSepbember Updatesのページでばらけていたので、まとめておきます

```sh
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install python3-edgetpu libedgetpu1-max
```




# この記事について
Jetson Nano に Google Coral Edge TPUを接続して、デモコードを動かします。

## 課題
Google Coral Edge TPUはaarch64環境をサポートしています。そのため、Jetson Nanoへのインストール自体は簡単にできます。
ただし、現時点(2019/05/01)でarmとaarch64ではPython3.5のみ対応しているようで、Jetson Nanoに標準で入っているPython3.6で実行すると下記のようなエラーが出ました。
このエラーの解決方法も記載します。

```sh:実行時エラー
import _edgetpu_cpp_wrapper
ModuleNotFoundError: No module named '_edgetpu_cpp_wrapper'
```

## 環境
- ホストPC
	- Windows 10 (64-bit)
	- Git Bash (sshコマンドが使えれば何でもいい。MSYS,Tera TermでもOK)
- ターゲット
	- Jetson Nano
	- jetson-nano-sd-r32.1-2019-03-18

JetsonNano上で直接操作する場合は、ホストPCは不要。僕はWindowsからssh越しに操作しました。


# Google Coral Edge TPU環境のインストール
https://coral.withgoogle.com/docs/accelerator/get-started/ 通りにやるだけです。

```
cd ~/
wget https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz -O edgetpu_api.tar.gz --trust-server-names
tar xzf edgetpu_api.tar.gz
cd edgetpu_api
bash ./install.sh
```

この状態でデモコードを実行すると、上述のエラーが発生します。
解決策として、以下の2つがあります。

1. Python3.5用edgetpuライブラリを、Python3.6用にも無理やり使う
2. Python3.5をインストールする

## 解決策1) Python3.6用ライブラリを無理やり用意する
edgetpuのライブラリは、`/usr/local/lib/python3.6/dist-packages/edgetpu/swig/` にインストールされます。
`ls`すれば分かると思うのですが、armとaarch用には、python3.5用のライブラリしか用意されていません。
以下コマンドで、コピーしてしまいます。

```sh:ライブラリのコピー
sudo ln -s /usr/local/lib/python3.6/dist-packages/edgetpu/swig/_edgetpu_cpp_wrapper.cpython-35m-aarch64-linux-gnu.so  /usr/local/lib/python3.6/dist-packages/edgetpu/swig/_edgetpu_cpp_wrapper.cpython-36m-aarch64-linux-gnu.so
```

注意:
デモコードはとりあえず動きました。ただ、予期せぬトラブルを招く可能性があるのでご注意ください。

仮想環境の場合は、
`ln -s /usr/local/lib/python3.6/dist-packages/edgetpu/swig/_edgetpu_cpp_wrapper.cpython-35m-aarch64-linux-gnu.so ~/.virtualenvs/env_py36_tfgpu_01/lib/python3.6/site-packages/_edgetpu_cpp_wrapper.cpython-36m-aarch64-linux-gnu.so`


## 解決策2) Python3.5をインストールする
素直にPython3.5を使うのが、正しい解決策な気がします。
が、aptからのインストールがうまくできなかったので、自前ビルドしました。(参考: https://tecadmin.net/install-python-3-5-on-ubuntu/ )

```sh:Python3.5のインストール
sudo apt-get install build-essential checkinstall
sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
wget https://www.python.org/ftp/python/3.5.6/Python-3.5.6.tgz
tar xzf Python-3.5.6.tgz
cd Python-3.5.6
sudo ./configure --enable-optimizations
sudo make altinstall
```

### 仮想環境を用意する
メイン環境を汚すのが嫌なので、仮想環境を用意します。事前に、`sudo pip install virtualenv virtualenvwrapper` とvirtuelenvの設定が終わっているとします。
なお、上記のPython3.5もaltinstallによって標準のpythonバイナリの邪魔をしないようにしています。

ラズパイのときもそうだったのですが、仮想環境上で再度edgetpuのpip installが必要でした。

```sh:仮想環境用意とedgetpuインストール
cd ~/edgetpu_api
mkvirtualenv --python=python3.5 env_py35_tpu
deactivate
workon env_py35_tpu
pip install edgetpu-1.9.2-py3-none-any.whl
```

## 実行する
後は、チュートリアル通り、以下コマンドで識別をするデモコードが動きました。

```sh:デモコードを動かす
cd ~/Downloads/
wget https://dl.google.com/coral/canned_models/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite \
https://dl.google.com/coral/canned_models/inat_bird_labels.txt \
https://coral.withgoogle.com/static/images/parrot.jpg
cd /usr/local/lib/python3.6/dist-packages/edgetpu/demo
python3 classify_image.py \
--model ~/Downloads/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite \
--label ~/Downloads/inat_bird_labels.txt \
--image ~/Downloads/parrot.jpg

# ---------------------------
# Ara macao (Scarlet Macaw)
# Score :  0.76171875
```


# 速度比較

| Environment | Inference time[msec] | Model |
|:-----------|------------:|:------------|
Jetson Nano + Edge TPU   | 2.5 | mobilenet_v2_1.0_224_quant_edgetpu.tflite
Raspberry Pi 3B+ + Edge TPU  | 9.9 | mobilenet_v2_1.0_224_quant_edgetpu.tflite
Jetson Nano (CPU)   | 89.7| mobilenet_v2_1.0_224_quant.tflite
Raspberry Pi 3B+ (CPU)  | 229.6 | mobilenet_v2_1.0_224_quant.tflite

TPU使用時の速度差は、USB3.0と2.0によるものだと思われます。TPU未使用時の速度差は、単にCPU性能によるものだと思われます。

ソースコードは全て共通のものを使用。(https://github.com/take-iwiw/JetsonNanoTest/tree/master/Python_EdgeTPU )
モデルはGoogle提供の[mobilenet_v2_1.0_224_quant.tflite](https://coral.withgoogle.com/models/ )を使用。[Edge TPU Model Compiler](https://coral.withgoogle.com/web-compiler/ )で変換済/未変換のモデルを入力することで、TPU有/無を切り替え。
「Jetson Nano (GPU)」は、Tensorflow Lite + GPUがうまくできなかったので無し。(そもそも、Tensorfow LiteのGPUサポートはAndroidとiOSだけ? 自分でビルドしたらできるかも)

## メモ
処理時間測定する前には、クロック周波数を固定(最大化)するのを忘れずに～。そして、100～1000回くらいループで回して平均を取るようにしましょう。

```sh:クロック最大化(JetsonNano)
sudo nvpmodel -m 0
sudo jetson_clocks
```

```sh:クロック最大化(RaspberryPi)
sudo apt install -y cpufrequtils
sudo cpufreq-set -g performance
cpufreq-info
```