2020年2月29日土曜日

Jetson NanoでTF-TRTを試す(JetPack4.3)

目的


(ずいぶん前になるが)JetPack4.3がリリースされたので、TF-TRT(TensorFlow integration with TensorRT)を使ってFP16に最適化したモデルでの処理時間を計測する。


動機


前回のブログ「Jetson NanoでTF-TRTを試す(Object detection)」で、よくわからない事象として「SSDLite MobileNet v3 LargeのPre-trained Modelで検出ができない」をあげていた。これはtensorflow/modelsにIssueを報告していたのだけど、アップされたmodelに問題があったとのことで新しいmodelがPRされた(2020.2.29時点ではまだマージされていない)。

問題が解決したのと、JetPackがアップデートされたので、再度、処理時間を計測しようと思った。


まとめ


  • SSDLite MobileNet v3 large / smallはJetpack 4.2 + TF1.14と比べ処理時間が遅くなっている。
  • MobileNet v3以外のDetection model(v1, v2など)は、NonMaxSupperssionをCPU実行に書き換えるとTF-TRT FP16のモデル変換に失敗する。
  • Classification model(MobileNet v1, v2)はJetPack 4.2 + TF1.14と比べ処理時間が若干だが早くなっている。

早くなっているね!で終わると思っていたのだが、つぶやいたとおりいろいろとあった。



環境


今回、3つのバージョンで計測した。
  • JetPack 4.2.2 + TF1.14
    JetPack: 4.2.2 (r32.2.1)
    TensorRT: 5.1.6
    TensorFlow: 1.14.0+nv19.10
    Python: 3.6.9
  • JetPack4.2.2 + TF1.15
    JetPack: 4.2.2 (r32.2.1)
    TensorRT: 5.1.6
    TensorFlow: 1.15.0+nv19.11
    Python: 3.6.9
  • JetPack4.3 + TF1.15
    JetPack: 4.3 (r32.3.1)
    TensorRT: 6.0.1
    TensorFlow: 1.15.0+nv20.1
    Python: 3.6.9

モデルの生成


TF-TRT FP16 のモデル変換は前回と同様、本家よりForkしたリポジトリを使用する。



なお、SSDLite MobileNet v3 large/smallのpre-trained modelのリンクは変更済みである。モデルの変換および、ベンチマークの際は、CUIモード&jetson_clocksで実行している。


Detection modelのベンチマーク


今回は対象を以下のモデルに絞って行った。
  • ssdlite_mobilenet_v2_coco
  • ssdlite_mobilenet_v3_small_coco
  • ssdlite_mobilenet_v3_large

TF-TRT FP16への変換、計測方法は前回のブログと同様である。
 NonMaxSupperssion(NMS)をCPU実行に書き換えて、TF-TRT FP16に変換。変換後、ベンチマーク用のスクリプト(初回の推論を除く100回の平均)で計測した。

JetPack4.2.2+TF1.15、JetPack4.3+TF1.15の場合、ssdlite_mobilenet_v2_coco モデルがモデル変換時に「Aborted (core dumped) 」となり失敗する。

2020-02-19 18:42:53.932561: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1304] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 1208 MB memory) -> physical GPU (device: 0, name: NVIDIA Tegra X1, pci bus id: 0000:00:00.0, compute capability: 5.3)
2020-02-19 18:43:21.378537: I tensorflow/compiler/tf2tensorrt/segment/segment.cc:460] There are 1379 ops of 31 different types in the graph that are not converted to TensorRT: Range, Sum, GreaterEqual, Where, Select, ConcatV2, Less, Fill, ExpandDims, Unpack, GatherV2, NoOp, TopKV2, Cast, Slice, Transpose, Pad, Placeholder, ResizeBilinear, Squeeze, Mul, Reshape, AddV2, Pack, Identity, NonMaxSuppressionV5, Shape, Greater, Sub, Minimum, StridedSlice, (For more information see https://docs.nvidia.com/deeplearning/frameworks/tf-trt-user-guide/index.html#supported-ops).
2020-02-19 18:43:22.630756: I tensorflow/compiler/tf2tensorrt/convert/convert_graph.cc:633] Number of TensorRT candidate segments: 2
2020-02-19 18:43:22.784932: F tensorflow/core/util/device_name_utils.cc:92] Check failed: IsJobName(job) 
Aborted (core dumped)

これは、この方のブログ「JetPack-4.3 for Jetson Nano」でも同様の事象が発生するとあり、NMSをCPU実行に書き換えることをやめると変換に成功するとあった(実際に成功する)。ssdlite_mobilenet_v3は変換に成功するため、単純にNMSのCPU実行の書き換えが問題でないと思われる。

このため、NMSを書き換えない場合も計測した。


NMSをCPU実行に書き換えた場合


Detection model
(force_nms_cpu=True)
Inference [ms]
JetPack4.2.2+TF1.14JetPack4.2.2+TF1.15JetPack4.3+
TF1.15
ssdlite_mobilenet_v2_coco_fp16.pb53.62--
ssdlite_mobilenet_v3_small_coco_fp1648.8964.9259.13
ssdlite_mobilenet_v3_large_coco_fp1666.0180.5073.45
-: モデル変換時にAborted (core dumped) が発生



NMSを書き換えない場合


Detection model
(force_nms_cpu=False)
Inference [ms]
JetPack4.2.2+TF1.14JetPack4.2.2+TF1.15JetPack4.3+
TF1.15
ssdlite_mobilenet_v2_coco_fp16.pb68.3978.2388.34
ssdlite_mobilenet_v3_small_coco_fp1699.22110.26119.78
ssdlite_mobilenet_v3_large_coco_fp16111.26120.45123.28



ベンチマーク結果


JetPack4.3 + TF1.15は
  • TF-TRT FP16 に変換できるモデルに限りがある。
    今のところはSSDLite MobileNet v3 small / large(SSDLite MobileNet EdgeTPU)が確認できている。
    (おそらく、モデルを学習した時のTensorFlowのバージョンが関係する?)
  • SSDLite MobileNet v3 small / largeは
    JetPack4.2.2 + TF1.14と比べ、推論の処理時間が遅くなっている。
    JetPack4.2.2 + TF1.15と比べ、推論の処理時間は早くなっている。
  • NMSのCPU実行への書き換えを行わなければモデルの変換に成功するが、推論時間は長くなってしまう(ためおすすめではない)。
  • (NMSになにかありそう???)

Classification modelのベンチマーク


こちらも、以下のモデルでベンチマークを行った。
  • mobilenet_v1_1.0_224
  • mobilenet_v2_1.0_224

(以前のブログ「Jetson NanoでTF-TRTを試す(Image Classification)その2」)と同様、TF-TRT FP16に変換。変換後、ベンチマーク用のスクリプト(初回の推論を除く100回の平均)で計測した。

こちらは、変換時に問題も発生することはなく、JetPack4.3 + TF1.15で処理時間が早くなっていることが確認できた。

Classification model
Inference [ms]
JetPack4.2.2+TF1.14JetPack4.2.2+TF1.15JetPack4.3+
TF1.15
mobilenet_v1_1.0_22423.6822.7421.58
mobilenet_v2_1.0_22427.4526.6924.95



2020年2月9日日曜日

Edge TPUをWindowsで動かす(Coral January 2020 Updates)

目的


Edge TPU Python APIをWindowsで動作させる。


動機


2020.1.29にCoral January 2020 Updatesがリリースされた。このリリースでWin, Macがサポートされた。このため、Windowsについて動作することを確認しようと思った。



自分が作成したEdge TPU Python APIを使ったサンプルを動作させるところまで。



Windows環境のセットアップ


環境


試した環境は以下の通り。
  • OS: Windows 10 Home, バージョン 2004, OSビルド 19041.21
  • CPU: AMD Ryzen 7 1700
  • メモリ: 16GB
  • Coral USB Accelerator


セットアップ


Python環境


Python環境はAnaconda 2019.10(Python3.7)をインストールする。

Anaconda Promptを立ち上げ、仮想環境を作成しておく。

> conda create -n coral anaconda


Edge TPU runtimeのインストール


Install the Edge TPU runtime - On Windows を参考に、Edge TPU runtimeをインストールする。ダウンロードしたファイルを解凍後、edgetpu_runtimeフォルダ内にあるinstall.batを実行する。


TensorFlow Lite interpreterのインストール


TensorFlow - Python quickstartを参考に、TensorFlow Lite interpreterをインストールする。

> pip install https://dl.google.com/coral/python/tflite_runtime-2.1.0-cp37-cp37m-win_amd64.whl

これでTensorFlow Lite APIからEdge TPUを使うことが可能。Run a model using the TensorFlow Lite AP のサンプルが動作できる。

[注意]
TensorFlow Lite API の場合、Edge TPUをPCに接続していない場合、
"Failed to load delegate from edgetpu.dll"
のエラーとなる。一見、Edge TPU runtimeのインストールに失敗していそうに思えるので注意。


Edge TPU Python APIのインストール


Coral - Edge TPU Python API for Mac and Windows を参考に、Edge TPU Python API for Windowsをインストールする。

> pip install https://dl.google.com/coral/edgetpu_api/edgetpu-2.13.0-cp37-cp37m-win_amd64.whl

これでインストールは完了。


動作確認


以前、作成したサンプルはRaspberry Pi + PiCamera用であったので、OpenCVベースに変更したものを用意した。とりあえず、現時点はObject detectionのサンプルのみ。

PCに接続できるカメラがないため、動画ファイル(スマホで撮影)入力。

モデルはSSDLite MobileNet EdgeTPU



その他


Edge TPU Compilerのバージョンアップ


Coral January 2020 Updatesでは、Edge TPU Compilerもバージョンアップした(2.0.291256449)。今回のバージョンで少しはまった点について。

SSDLite MobileNet EdgeTPU に含まれるTF-Liteモデル(Full integer quant model)をEdge TPU Compilerでコンパイルしたところ、推論実行時に
"ValueError: Dectection model should have 4 output tensors!This model has 12."
でエラーとなってしまった。

前回のEdge TPU Compiler(2.0.267685300)では問題なく、モデルも変わってはいない。

原因は、もともとのTF-Liteモデルが確かにoutputが12個あったので、Edge TPU Python APIが期待するoutputの個数ではなかったためである。

通常、TF-Liteモデルを生成する際、tocoで4つのoutput_arraysを指定するはずだが、SSDLite MobileNet EdgeTPUのpre-trainedモデルには異なるoutputが指定されていたと思われる(おそらく、もともとはPixel4向けなのでpostprocessingが異なるのかもしれない)。なので、今回のバージョンアップでは正しくコンパイルできるようになった...ということかもしれない。

SSDLite MobileNet EdgeTPUはcheckpointからexport、tocoで変換することで、Edge TPUで動作することは確認できた。

(もとのSSDLite MobileNet EdgeTPUのTF-Liteモデルはどうやって使うのだろうか?)

2020年2月2日日曜日

TensorFlow Lite for microのHello worldサンプルをM5StickVで動かす(その2)

前回


前回のブログでは、TensorFlow Lite for microのサンプル(Hello world)をM5StickV向けにビルド、動作させるところまでを書いた。出力はコンソール出力だけで、M5StickVのLCDには何も表示しない。


目的


今回は、M5StickVのLCDに表示を行うところをメインにする。
こんな感じである。




参考



LCDに表示するまでの道のり


LCDに表示するにはHWの制御がかなり必要である。自前でやるのもよいが、今回はsipeedが提供するMaixPyに含まれるライブラリを使用することにする。

前回のプロジェクトに追加・変更する方針とする。




sipeed / MaixPyのMaixPyのSDK


もともと、Micropython 用の環境であるが、SDKと利用して独自のcプロジェクトをビルドすることができる。


ただ、C++はビルドできないため、SDKのみを利用することにした。

components配下のSDKの部分を利用する。以下のフォルダを利用した。
  • boards
  • drivers
  • kendryte_sdk
  • utils


sipeed/MaixPyのSDKをプロジェクトに追加


プロジェクトに追加する。


sipeed/MaixPyのSDKをC++から呼び出せるように変更


sipeed/MaixPyのSDKはC++から呼び出すことを考慮していない箇所が多数ある。このため、使用する部分のヘッダを変更する。

extern "C" の追加し、呼び出し可能とする。

今回は以下のヘッダを修正。

TensorFlow lite for microのソース変更


以下の処理を追加する。
  • main.ccでLCDを含むHWの初期化
  • output_handler.ccで描画の更新


HWの初期化


src/micro/tensorflow/tensorflow/lite/micro/examples/hello_world/main.ccで行う。
  • HWの初期化を行う。
    m5stick_init()
    (BUTTON B長押しの電源OFFもできるようになったりする)
  • setup_lcd()でLCD初期化を行う。

man.ccはこのような感じになる。



出力値に応じた点の描画


src/micro/tensorflow/tensorflow/lite/micro/examples/hello_world/output_handler.ccで行う。

STM32F746の実装を参考。LCD出力用の関数をsipeed/MaixPyのSDKを使用する。ただ、元の実装では円を描画しているが、sipeed/MaixPyのSDKには用意されていない。今回は矩形描画で代替えした。

使用した関数は以下。
  • lcd_get_width ... LCDの幅を取得
  • lcd_get_height ... LCDの高さを取得
  • lcd_clear ... LCDのクリア
  • lcd_fill_rectangle ... 矩形を描画

output_handler.ccはこのような感じになる。


最後に


前回、今回とM5StickVでTensorFlow Lite for microのサンプルをビルドするやり方を記載した。M5StickVには6軸センサやカメラがあるので、他のサンプルも行けると思うのでチャレンジしてみたい。