動機
"Co-compiling multiple models"
https://coral.withgoogle.com/docs/edgetpu/compiler/
まとめとかいろいろ
(USB AcceleratorでかつUSB2.0の場合)
- 複数モデルを連続して使用する(複数回の推論を行う)場合は、Edge TPU Compilerの同時コンパイルは有効。
- 複数のモデルがEdge TPUのメモリに収まるかが重要。
Edge TPUのメモリに収まらなかったモデルの推論の処理時間が遅くなってしまう。どちらのモデルを優先で使うかを考えてコンパイルする順序をかえる。このため、コンパイルする順序を変える(小さいモデルを先にする)と改善する(場合がある)。 - ただし、Edge TPUのメモリに収まらなかった場合でも、同時コンパイルしない場合と比べ、トータルの処理時間は早くなる。
- Dev Board(PCIe)やUSB3.0と接続した場合、推論の時間がどの程度変わってくるか不明(どちらの環境も持っていないので...)。
環境
- Raspberry Pi 3 B+
- Edge TPU USB Accelerator(接続は"最大動作周波数")
- Edge TPU API Release1.9.2 (Apr 2019)
- Edge TPU Compiler (Offline compiler) Version 1.0.249710469
- 使用モデルはPre-trained model
複数モデルのコンパイル
使用モデル
Pre-trained modelのTF-Lite modelを使用。
項番の順にコンパイルに指定及び、推論を行う。
項番の順にコンパイルに指定及び、推論を行う。
- Model1 : mobilenet_v2_1.0_224_inat_bird_quant.tflite
- Model2 : mobilenet_v2_1.0_224_inat_plant_quant.tflite
コンパイル
コンパイルはoff-line compilerのみ。コマンドライン引数で複数のモデルを指定する。コンパイル後、Edge TPU モデルが生成される。1つのモデルにまとめられるわけではなく、指定したTF-Liteモデルの分、生成される(最初は1つにまとめられると思っていた)。
コマンドライン引数とコンパイル時の結果は以下の通り。
edgetpu_compiler Model1 Model2
コマンドライン引数とコンパイル時の結果は以下の通り。
# edgetpu_compiler -o output/ -s mobilenet_v2_1.0_224_inat_bird_quant.tflite mobilenet_v2_1.0_224_inat_plant_quant.tflite Edge TPU Compiler version 1.0.249710469 INFO: Initialized TensorFlow Lite runtime. Models compiled successfully in 1390 ms. Input model: mobilenet_v2_1.0_224_inat_bird_quant.tflite Input size: 3.37MiB Output model: output/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite Output size: 3.89MiB On-chip memory available for caching model parameters: 6.91MiB On-chip memory used for caching model parameters: 3.75MiB Off-chip memory used for streaming uncached model parameters: 0.00B Number of Edge TPU subgraphs: 1 Total number of operations: 65 Operation log: output/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.log Operator Count Status FULLY_CONNECTED 1 Mapped to Edge TPU SOFTMAX 1 Mapped to Edge TPU ADD 10 Mapped to Edge TPU AVERAGE_POOL_2D 1 Mapped to Edge TPU CONV_2D 35 Mapped to Edge TPU DEPTHWISE_CONV_2D 17 Mapped to Edge TPU Input model: mobilenet_v2_1.0_224_inat_plant_quant.tflite Input size: 4.76MiB Output model: output/mobilenet_v2_1.0_224_inat_plant_quant_edgetpu.tflite Output size: 5.22MiB On-chip memory available for caching model parameters: 3.16MiB On-chip memory used for caching model parameters: 2.49MiB Off-chip memory used for streaming uncached model parameters: 2.59MiB Number of Edge TPU subgraphs: 1 Total number of operations: 65 Operation log: output/mobilenet_v2_1.0_224_inat_plant_quant_edgetpu.log Operator Count Status ADD 10 Mapped to Edge TPU AVERAGE_POOL_2D 1 Mapped to Edge TPU CONV_2D 35 Mapped to Edge TPU DEPTHWISE_CONV_2D 17 Mapped to Edge TPU SOFTMAX 1 Mapped to Edge TPU FULLY_CONNECTED 1 Mapped to Edge TPU
Edge TPUのメモリのサイズ(On-chip memory)に注目すると、2つのモデルがEdge TPUのメモリに割り当てられている。そして、2つのモデルをコンパイルした場合、Edge TPUのメモリに収まり切らないため、2つ目のモデルのはみ出す分が、"Off-chip memory"(外部メモリ)割り当てられている。
1つ目のモデルのコンパイル
- 1つ目のモデルがすべて、Edge TPUのメモリに割り当てられている(3.75Mib)。
- Edge TPUのメモリの空きは3.16MiB(6.19 - 3.75Mib)。
On-chip memory available for caching model parameters: 6.91MiB On-chip memory used for caching model parameters: 3.75MiB Off-chip memory used for streaming uncached model parameters: 0.00B
2つ目のモデルのコンパイル
- 2つ目のモデルのうち2.49Mib分が、Edge TPUの空きメモリから割り当てられる。
このとき、Edge TPUの空きメモリは3.16Mibなので0.67Mib分の余白あり。 - 外部メモリに2.59Mibが割り当てられた。
On-chip memory available for caching model parameters: 3.16MiB On-chip memory used for caching model parameters: 2.49MiB Off-chip memory used for streaming uncached model parameters: 2.59MiB
(ご指摘いただいて気づいたのだが)
Edge TPU Compilerはコンパイル時にモデルを識別するための"caching token"を付与する。推論の実行時にEdge TPUのメモリに展開されたモデルと、推論を行うモデルの"caching token"を比べて、異なれば推論を行うモデルをEdge TPUのメモリに展開する。このため、毎回異なるモデルでの推論を行った場合は、都度Edge TPUのメモリへの展開が行われるため、推論時間が遅くなってしまう。
複数モデルをコンパイルしたときは"caching token"が同一なのでEdge TPUのメモリが書き換わらないため、推論の処理時間が早くなる。
※より正確にはParameter data cachingを参照。
モデルの可視化
visualize.pyでコンパイルしたEdge TPU モデルを可視化すると、Tensorsが通常と異なることが分かる。
下の図は、通常のコンパイル(マルチモデルでない)した場合。
MoblieNetV2の各Tensorsが分かる。
MoblieNetV2の各Tensorsが分かる。
MoblieNet V2 のPre-trained modelを可視化 |
下の図は、マルチモデルでコンパイルした場合。
Inputと中間のTensorsがすべて、map/TensorArrayStack/TensorArrayGatherV3となっている。
MoblieNet V2のマルチモデルのコンパイルした結果を可視化 |
ベンチマーク
方法
Pythonスクリプトを自作して計測。コードはここ。
単純に2つのモデルの推論を繰り返し行う。推論の処理時間はEdge TPUのAPI(get_inference_time)を使用。
計測の概要は以下。
単純に2つのモデルの推論を繰り返し行う。推論の処理時間はEdge TPUのAPI(get_inference_time)を使用。
計測の概要は以下。
- モデルはImage Classificationのモデル。
- 推論の処理時間を計測。比較用に
モデルが1つの推論
モデルが2つの推論・別々にコンパイルしたモデルを使用
モデルが2つの推論・同じモデルを使用
モデルが2つの推論・同時にコンパイルしたモデルを使用 - 推論の初回と2回目以降は処理時間が異なる(初回はモデルを転送している)ので、別々に計測。
初回の推論 : 10回計測した平均
2回目以降の推論 : 100回計測した平均
初回の推論時は、ClassificationEngineクラスの生成でかなり時間がかかるので回数を落としている。
初回の推論
[モデルが1つの場合]
[モデルが2つの場合]
2回め以降の推論
[モデルが1つの場合]
[モデルが2つの場合]
結果
初回の推論時
- 同時コンパイルの有無に関係なく、Model1、2ともほぼ同じ処理時間がかかっている。
- ただ、2つ目のモデルの処理時間が若干遅い(約40msほど遅い)。
- Model1, 2に同一のモデルを指定した場合は、推論時間に差はない。
Model2の推論時には、すでにモデルがEdge TPUのメモリに展開されているので処理時間は少なくなるはず?なぜか処理時間が変わらない結果となった。
2回目以降の推論時
- 同時コンパイルしない場合は、初回の推論とほぼ同じぐらいの処理時間がかかっている。
これは、推論ごとにEdge TPUのメモリの入れ替えが発生しているためと推測。 - 同時コンパイルした場合は、効果が確認できる。
1つ目のモデルは、モデルが1つの場合と同じ処理時間。
2つ目のモデルは若干遅い(約70ms)これは、外部メモリからモデルをロードするためと推測。同時コンパイルしない場合と比べ、約190msの短縮。 - Model1, 2に同一のモデルを指定した場合は、推論時間に差はない。
Edge TPUのメモリの切り替えが発生しないためと推測。
その他
1つ目のモデルで大半のEdge TPUのメモリを使用してしまう場合の組み合わせを確認。
指定したTF-Liteモデルは以下。
Model1 : inception_v3_299_quant.tflite
Model2 : mobilenet_v2_1.0_224_inat_plant_quant.tflite
コンパイルした結果。
(1つ目のinception_v3でほぼすべてのEdge TPUのメモリが専有されてしまう)
# edgetpu_compiler -o output/ -s inception_v1_224_quant.tflite mobilenet_v2_1.0_224_inat_plant_quant.tflite Edge TPU Compiler version 1.0.249710469 INFO: Initialized TensorFlow Lite runtime. Models compiled successfully in 2590 ms. Input model: inception_v1_224_quant.tflite Input size: 6.38MiB Output model: output/inception_v1_224_quant_edgetpu.tflite Output size: 6.93MiB On-chip memory available for caching model parameters: 6.53MiB On-chip memory used for caching model parameters: 6.53MiB Off-chip memory used for streaming uncached model parameters: 182.19KiB Number of Edge TPU subgraphs: 1 Total number of operations: 83 Operation log: output/inception_v1_224_quant_edgetpu.log Operator Count Status CONCATENATION 9 Mapped to Edge TPU CONV_2D 58 Mapped to Edge TPU RESHAPE 1 Mapped to Edge TPU SOFTMAX 1 Mapped to Edge TPU AVERAGE_POOL_2D 1 Mapped to Edge TPU MAX_POOL_2D 13 Mapped to Edge TPU Input model: mobilenet_v2_1.0_224_inat_plant_quant.tflite Input size: 4.76MiB Output model: output/mobilenet_v2_1.0_224_inat_plant_quant_edgetpu.tflite Output size: 6.04MiB On-chip memory available for caching model parameters: 1.50KiB On-chip memory used for caching model parameters: 1.25KiB Off-chip memory used for streaming uncached model parameters: 5.86MiB Number of Edge TPU subgraphs: 1 Total number of operations: 65 Operation log: output/mobilenet_v2_1.0_224_inat_plant_quant_edgetpu.log Operator Count Status DEPTHWISE_CONV_2D 17 Mapped to Edge TPU SOFTMAX 1 Mapped to Edge TPU FULLY_CONNECTED 1 Mapped to Edge TPU ADD 10 Mapped to Edge TPU AVERAGE_POOL_2D 1 Mapped to Edge TPU CONV_2D 35 Mapped to Edge TPU
推論結果(2回目以降の推論)
同時コンパイルした場合は、しない場合と比べ、約170msの短縮。
ただし、Model2(MoblieNet V2)の処理時間はかなり遅い(1つだけのモデルで推論した場合は約10ms程度)。
1つ目と2つ目のモデルを入れ替えた場合
Model1 : mobilenet_v2_1.0_224_inat_plant_quant.tflite
Model2 : inception_v1_244_quant.tflite
コンパイルした結果。
1つ目のMobileNetV2のモデルサイズは小さいため、2つ目のInception V3にもEdge TPUのメモリが割り当てられる(1.45MiB)。
# edgetpu_compiler -o output/ -s mobilenet_v2_1.0_224_inat_plant_quant.tflite inception_v1_224_quant.tflite Edge TPU Compiler version 1.0.249710469 INFO: Initialized TensorFlow Lite runtime. Models compiled successfully in 2534 ms. Input model: mobilenet_v2_1.0_224_inat_plant_quant.tflite Input size: 4.76MiB Output model: output/mobilenet_v2_1.0_224_inat_plant_quant_edgetpu.tflite Output size: 5.22MiB On-chip memory available for caching model parameters: 6.53MiB On-chip memory used for caching model parameters: 5.08MiB Off-chip memory used for streaming uncached model parameters: 0.00B Number of Edge TPU subgraphs: 1 Total number of operations: 65 Operation log: output/mobilenet_v2_1.0_224_inat_plant_quant_edgetpu.log Operator Count Status ADD 10 Mapped to Edge TPU AVERAGE_POOL_2D 1 Mapped to Edge TPU CONV_2D 35 Mapped to Edge TPU DEPTHWISE_CONV_2D 17 Mapped to Edge TPU FULLY_CONNECTED 1 Mapped to Edge TPU SOFTMAX 1 Mapped to Edge TPU Input model: inception_v1_224_quant.tflite Input size: 6.38MiB Output model: output/inception_v1_224_quant_edgetpu.tflite Output size: 6.93MiB On-chip memory available for caching model parameters: 1.45MiB On-chip memory used for caching model parameters: 1.45MiB Off-chip memory used for streaming uncached model parameters: 5.16MiB Number of Edge TPU subgraphs: 1 Total number of operations: 83 Operation log: output/inception_v1_224_quant_edgetpu.log Operator Count Status RESHAPE 1 Mapped to Edge TPU SOFTMAX 1 Mapped to Edge TPU AVERAGE_POOL_2D 1 Mapped to Edge TPU MAX_POOL_2D 13 Mapped to Edge TPU CONCATENATION 9 Mapped to Edge TPU CONV_2D 58 Mapped to Edge TPU
推論結果(2回目以降の推論)
1つ目と2つ目のモデルを入れ替える前と比べて、約20msの短縮。
Model1(MobileNet V2)は、1つだけのモデルで推論した結果とほぼ変わらない。
Model2(Inception V1)の処理時間が遅くなっているがトータルとしてMoblieNet V2が早くなった分、改善している。
[2019/6/25 指摘を頂いて追記]
モデルを入れ替えることによって推論時間のトータルが改善することは意味がない。
(今回のケースではたまたま処理時間が改善しているように見えるだけであると推測)
モデルを入れ替える場合はどちらのモデルが使用頻度が高いか(Model1のほうが使用頻度が高ければ順序を先にする)を考慮したほうがメリットがある。