Edge AIアクセラレータの速度性能に関して

# この記事について
Edge AIではリアルタイム性が求められることが多いです。
高負荷なDeep Learning演算をエッジで行うため、最近は多くのEdge AIアクセラレータがリリースされています。
個人でも手に入る有名どころでは、Edge TPUやMovidius NCS、Jetson Nanoがあります。
今後もこの流れは続いていくと思います。

これらのデバイスメーカーや、個人のサイトでは速度性能のベンチマークを記載したり比較しています。
その際に、自分が見ている数字は何の速度なのか? 自分は何の速度を知りたいのか? をちゃんと理解しましょう、という内容です。

要約

- Deep Learningに関する速度性能として、主に以下の3つが考えられると思います
    - FLOPS (TOPS)
        - ハードウェアとしてのスペック性能
    - 推論時間
        - AIアクセラレータが有効なのは、基本的にはこの部分のみです
        - AIアクセラレータの比較や、既存のシステムに組み込む際の処理時間見積もりにはこの数字を使った方が良いと思います
    - システム全体の処理時間
        - 推論時間にその他の処理(入力、前処理、後処理、出力、など)も含めた時間
        - 最終プロダクトとしての速度(fps)となります
        - プロダクトの性能指標としてはこの数字を使った方が良いと思います

## 注意
思いつくままにつらつら書いてしまいました。
読む方が、個人で開発をしている方、メーカーなどでAIアクセラレータ導入を考えている方、によって考え方は異なると思います。何かご意見がございましたら、コメントいただけると嬉しいです。

# 処理の定義
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214268/2861f701-1635-3a6b-8c9a-72edd2939c80.png)


入力画像に対して物体検知を行うシステムを例に、どのような処理があるかを考えます。

1. 画像入力 (Input)
	- カメラや動画から画像を読み込む処理です
2. 前処理 (Pre-processing)
	- 1で入力した画像を、ディープラーニングモデルに食わせられる形式に変換します。例えば以下のような処理があります。
		- フォーマット変換: YUV -> BGR
		- リサイズ: 1280x720 -> 300x300
		- 正規化: 値の範囲を0～255 -> 0.0 ～1.0
3. 推論処理 (Inference)
	- 2で変換したデータを、ディープラーニングモデルに入力し、結果が出力されるまでの時間
4. 後処理 (Post-processing)
	- 3のディープラーニング出力結果を、検知結果の座標などに変換します
5. 結果出力 (Output)
	- 結果を画面に描画したりします

# 速度性能の指標
## FLOPS
1秒間に何回の演算ができるかという、ハードウェアスペック値です。

- FLOPS (TFLOPS)
    - (Tera) Floating-point Operations Per Second
    - 浮動小数点(FP32, FP16)演算を1秒間に何回できるか
- OPS (TOPS)
    - (Tera) Operations Per Second
    - 整数(INT8)演算を1秒間に何回できるか

実速度と同じになるかは別として、スペック比較する際にはもっとも手軽です。



## 推論時間のみ
速度性能として、推論処理にかかる時間のみを見ます(上述の3のみ)。
純粋なディープラーニングの速度を見ることが出来ます。
推論時間=○○[msec]とかで表されます。

## 画像入力～結果出力までの合計
速度性能として、推論を含む全ての処理時間合計を見ます(上述の1～5全て)。
システム全体としての速度性能を見ることが出来ます。
いわゆるfpsになります。レイテンシ=○○[msec]という表現になることもあると思います(特に、サーバにデータをアップロードして結果をブラウザに表示するときなど)

- 使用するデバイス(CPU、メモリなど)によって、この性能は変わります
    - というのもあって、評価用ボードを出しているデバイスメーカーもあります。が、
- 同じデバイスを用いても、以下の要因によって性能が変わります
	- 実装言語
		- 前処理/後処理の実装が、PythonかC++かで速度は変わります。
	- GPU, ISP使用
		- hobby useだと無いかもしれませんが、リサイズなんかはISP(Image Signal Processor)で処理したら一瞬です。
		- ISPが無いにしても、GPUで処理するかCPUで処理するかで大幅に変わります。
	- マルチコア実装の有無
		- 上述のGPU,ISPが無くても各種処理をマルチコア実装するかどうかでも速度は変わります
	- マルチプロセス(マルチスレッド)実装の有無
		- 上述の1~5をシリアルに実行するかパイプライン状に実装するかでもfps(!=処理時間)は変わります
		- この場合、fpsとレイテンシの意味合いが変わってきます
	- 画像入力方法
		- カメラ入力にOpenCVを使うのか? v4l2直叩きか? フォーマットによっても速度は変わります
	- 実装の上手い下手
		- 後処理で、heat mapから結果をゴニョゴニョする処理なんかは実装の上手い下手によって速度も変わりそう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214268/25d1a89b-2523-f82f-5105-30a95b241897.png)


## どっちの指標がいいの?
どちらが良い悪いというわけではなく、目的に応じて使い分けるべきだと思います。
個人的には以下のように考えています。

### 推論時間を使った方が良いケース
- AIアクセラレータそのものの性能を見るとき、比較するとき
- 既存システムに組込むときの処理時間見積もり (例えば、既存のデジタルカメラに顔検知を新たに組み込もう、というとき)

理由は以下の通りです。

- 推論時間はコードの書き方の影響を受けづらいため、純粋にAIアクセラレータの比較ができる
	- ただし、モデル、モデル精度(FP32,FP16,INT8)やフレームワークの差分は考慮する必要があります
- 推論時間以外の処理は、使用目的によって異なる
	- 例えば、入力がOpenCVによるカメラ入力か、ISP部が書き込んだメモリから読み込むか、によっても処理時間は異なります
	- 例えば、結果出力を出力するかどうかによっても異なります
	- 実際、検知枠を表示するなんて、デモ用途以外ではあまりないと思います。画面出力がない商品を作っているのに、画面出力ありの速度性能を参考として出されても困りますよね?
- 推論時間以外の処理時間は、使用するCPUやその他環境(実装方法など)によって大きく変わる
	- 例えば、Raspberry Pi Zero + Edge TPUとJetson Nanoを、リサイズ処理時間まで含めて比較するのはunfairです
		- 個人が趣味開発するための環境を検討する分には良いと思います(検討時の環境=最終的に使用する環境だから)
		- ですが、メーカーの人が既存システムに導入するアクセラレータを検討する際には、これでは正しい比較ができないと思います

ということで、Edge AIアクセラレータ単体の速度性能としては、推論時間だけをまずは確認すべきだと思います。
そこから、実プロダクトでの性能を見積もったり、速度が最大になるように設計、実装、チューニングするのは、使用者が考えることです。
逆に、推論だけの処理時間が分からないと、その見積もりもできないので、デバイスメーカーには純粋な推論時間のデータを提示していただきたいところです。

### 全体の処理時間を使った方が良いケース
デバイスメーカーさんや、比較ベンチマークを作っている方には推論時間そのものを提示していただきたいと思っています。個人的には。

その一方で、全体の処理時間を使った方が良いケースも当然あると思います。例えば、以下のケースです。

- 商品・システム全体の性能を示したい場合
	- 最終プロダクトを見る人にとって、興味があるのは全体としてどれくらいの速度が出るかどうかです。この速度を高速化するのは、システム設計者や組み込み屋さんの腕の見せ所です。というか、その設計、実装次第で速度は大きく変わります。
	- 例えば、会社のお偉いさんやお客さんに、「この画像処理システムの推論時間は○○ミリ秒です。他の処理はありますが、そっちは僕の管轄じゃないので知りません」。と言ったら殺されると思います。彼らが知りたいのは、「この商品は○○FPSの速度が出ます。これはほぼリアルタイムで処理出来ているということです」、といった分かりやすい結果です。
- めっちゃ高性能なデバイス(CPU、メモリなど)を使っている場合
	- Jetson AGX Xavierレベルだと、画像処理時間は微々たるもので、推論時間が大部分を占めると思います。その場合は、そもそも特に細かく区別しないでもよいかもしれません。
- 推論エンジン(やGPU)をパッケージ化してプラットフォームとして販売している商品も出ています。これらの場合には、プラットフォームとしての速度性能を示してもらった方が分かりやすいかもしれません。例えば以下のような商品があります。
	- NVIDIA DRIVE AGX
	- OKI AE2100


## みんなどうしているのか?
### Google Coral Edge TPU
https://coral.withgoogle.com/docs/edgetpu/benchmarks/

ベンチマークでは推論時間[msec]を載せています。分かりやすいですね。

### Jetson Nano
https://developer.nvidia.com/embedded/jetson-nano-dl-inference-benchmarks

単位はFPSとなっていますが、推論時間のみのようです。(Inferences per second (the network time) https://devtalk.nvidia.com/default/topic/1049802/jetson-nano/object-detection-with-mobilenet-ssd-slower-than-mentioned-speed/3 )

(ただ、Jetson Nano内の/usr/src/tensorrt/samples/python/uff_ssd/detect_objects.py を見ると、inference timeとしてPILの画像読み込みを含んでいたり、
ベンチマークで比較として載せているEdge TPUの性能がCoralのページよりも遅いので、何か別の処理も含んでいるように感じます。)

### Allanさんのベンチマーク
https://medium.com/@aallan/benchmarking-edge-computing-ce3f13942245

こちらは、推論時間+リサイズ以外の前処理+後処理が入っています。
Allanさんも本記事と同じようなことを言ってくれています。


> While we resize the image before we start timing our inferencing, we’re still passing an image to TensorFlow which then has to take this and convert it into something that our model can use. Google’s numbers are for the inferencing stage on its own, that’s a much cleaner (and shorter) operation. I’d argue that my benchmark is a bit more representative of what people will be doing out in the world. Google’s numbers are fine, but most people aren’t really interested in the time it takes between passing a tensor to the model and getting a result.


# その他考えるべきこと
速度性能以外で、AIアクセラレータ、デバイス導入に際して考慮すべき点

## リソース使用量
- GPU
	- Deep Learning処理以外でもGPUを使う可能性があります。リソースの取り合いには注意です
- CPU 1
	- 使用するアクセラレータによっては、CPU側での処理が必要なケースがあります(例. CPU側にオフロードされたEdge TPU演算)
- CPU 2
	- ほとんどのケースでは、「処理を高速化する」というのがAIアクセラレータを使用する目的だと思います。が、CPUを使わずに処理できる、という目的もあります。例えば、Movidius NCSなんかは1本刺したくらいだとぶっちゃけそんなに速くありません。が、CPUを空けられるというのは嬉しいメリットです。
- メモリ帯域
	- 手元ではうまく動いていたのに、他のアプリと組み合わせて動かしたら、帯域が足りずに速度が全然でないということがあったりなかったり。。。

## 熱
- 本記事では処理時間に着目しましたが、実際に商品に組み込むことを考えると、熱は当然考慮すべき項目です。
- PoCは開発しやすいGPUでやっていたけど、いざ商品化の段階では熱問題のためにやり直しになることあるとかないとか。。。

## インターフェイス、入手性
- 評価する際の注意
	- USB3デバイスをUSB2しかないボードで評価して遅いとかいうのはunfairです。
- 実プロダクトに導入する際の注意
	- USBドングルを刺せる商品ですか?
	- ベンダはUSB以外のオプション (チップ提供など)を用意していますか?
	- 入手性は大丈夫ですか?




# (おまけ)処理時間測定をする際の注意点
- 100回くらいループ実行して、処理時間の平均を取るようにします。測定誤差をなくしたり、DFSの影響をなくすためです。
	- 場合によっては、初回の呼び出しは時間がかかるので、除く
	- 逆に、システムによっては、毎回「初回実行」相当の動きになるものもあるかと思います。その場合には測定方法を変える必要があります
- CPUやGPUの動作周波数を固定にする。ほとんどの場合、最大周波数に設定します。(コマンド例↓)
    - `sudo apt install -y cpufrequtils && sudo cpufreq-set -g performance`
    - `sudo nvpmodel -m 0 && sudo jetson_clocks`
- 外乱の影響を受けないようにする
	- 測定中は、他の処理は止める。うっかりソフトウェアアップデートなどが走らないように。