Last updated on

WoLNamesBlackedOut開発日記 物体検出の前後処理を改善する


TensorRTでもDirectMLでもGPU負荷が約50%

WoLNamesBlackedOutは物体検出の推論に、TensorRTとDirectMLというものを使っています。
TensorRTはGEFORCE RTX専用、DirectMLはどのGPUでも利用できるWindows汎用でそこそこ速いものです。
ただどちらを利用しても物体検出処理のGPU負荷が50%程度で、不思議でした。
なんなら後で行う音声合成のFFmpeg動画処理の方がGPU負荷が高いくらい。

TensorRTもDirectMLも、物体検出では手を抜いているのではないか?

例えば

  • GPU負荷や電力にリミットをかけているのではないか
  • 物体検出の前処理や後処理に時間がかかっており、GPUがそれらが来るまでの休んでいる時間が長いのではないか

などなど。

前者については、特に設定を変更した覚えもなく、何かしら追加で制御していることもなさそうなので、無罪。

後者は怪しくて。
前処理のリサイズや、後処理での黒塗りやモザイクなどはOPENCVを利用しているのですが、仮に実装したままで全てCPU処理になっています。
OPENCVの処理をCUDAやOPENCLのGPU処理にして改善できないか、やってみることにしました。

 

まずはOPENCVのビルドから

OPENCLはともかく、CUDAを利用するにはOPENCVをビルドするところから始めないといけません。
これが苦労しました。

OPENCVのビルド自体は以前もしたことがあったのでスムーズだったのですが、
Windowsから利用したことはあまりなかったので、変に苦労しました。
結局、プロジェクトにCUDA Toolkitのdllを追加して、ビルド時コピーする対象にしていなかった、のが原因でした。
これに気づくのに1週間近くかかった気がします、たぶん。

 

ビルドしたOPENCVをWoLNamesBlackedOutに適用してみる。

まずはビルドした新しいOPENCVに置き換えだけを行い、従来と同じCPU処理で実行してみます。
同じCPU処理なので従来から大きく劣化してなかったらいいな、と思っていたのですが、

  • TensorRT:53FPS → 70FPS に処理速度改善
  • DirectML:39FPS → 38FPS とあまり変わらず

デバッグでの実行なので多少遅くなるのは仕方がないのですが、TensorRTは何もしてないの速くなってしまいました!
OPENCVのビルドで、CPUでも速くなるように、といろいろオプションを盛ったのですが、それが良い結果につながったのかもしれません。

やはり物体検出の前処理や後処理がボトルネックになっていそう。
TensorRTの結果を見て確信に変わりました。

次のように適用してみようと考えています。

  • TensorRT+OPENCV-CUDA
  • DirectML+OPENCV-OPENCL

OPENCV-CUDAを利用すると、前処理、TensorRT、後処理と、ずっとGPUメモリ上で処理ができるようです。CPUーGPUのメモリ移動はだいたい遅いので、ずっとGPUで処理ができるというのは大きなメリットで、期待できます!

OPENCV-OPENCLは、単体ではそこそこ速かったので、DirectML利用時の前処理、後処理に採用し、処理速度が改善できないか、試してみることにしました。

 

DirectML+OPENCV-OPENCLの適用

まずはOPENCV-OPENCLを適用してみることからやってみました。
DirectMLは、CPUメモリを参照するため、前処理のためにOPENCL UMATにアップロード、DirectMLのためにダウンロード、後処理のためにアップロード、結果をダウンロード、とCPUーGPU間の移動が多い形に。
これでは遅かったので、後処理だけOPENCL処理に、としてみましたが、やはりそれでも微妙に元より遅くなってしまいます。

どうも、そもそもこちらの処理では、DirectML自体がボトルネックとなっているようです。前処理や後処理は直接のネックにはなっておらず、CPU処理でも十分に間に合う速度となっている様子。

RADEON、OPENCLと相性のいい、ONNXRUNTIMEのEPがないかと調べてみたのですが、Windows環境のRADEONで一番速いのはDirectMLということみたいです。LinuxだとMIGraphXやROCmとか使えることもありそうなのですがー。
ROCmやHIPとかの発展に期待かなー?

DirectMLについては、従来通りのCPUによる前処理、後処理とすることにしました。

 

TensorRT+OPENCV-CUDAの適用

実はまだやってません。
ただ何もせずに70FPSできたので、すごく期待しています!
もしかすると100FPSとかいけるんじゃないかな?無理かな?
今週末くらいにトライしてみたいと思ってます。
OPENCV-CUDA~TensorRTだと、サンプルコードも多いかもしれないかな?

TensorRTの方だけですが、現状よりは改善しそうな感じなので、よかったです!