InsightFaceをGPUで動かしてみた
目次
- InsightFaceとFastAPIで顔検出サーバを作ってみた
- InsightFaceの顔検出結果をNext.jsで可視化してみた
- InsightFaceで顔認証(特徴量抽出、比較)してみた
- InsightFaceをGPUで動かしてみた(本記事)
- InsightFaceを使って動画から顔検出してみた
- InsightFaceの顔検出結果をブラウザ上で動画にオーバーレイ表示してみた
初めに
ここ半月で3本に渡り、InsightFaceに関する記事を書きました。
これまではすべてCPU上で動作させていましたが、実際に顔検出に使用するには少々遅いので、NVIDIAのGPU上で動かしてみました。
結果から言えば、あっさりと動作しました。
InsightFaceをGPUで動かす
InsightFaceをGPUで動かすためには、以下の2箇所を修正する必要がありました。
-
onnxruntime
パッケージをonnxruntime-gpu
パッケージに変更する。 - ベースイメージを、NVIDIA Container Runtime用のDockerイメージに変更する。
具体的な修正箇所は、以下のPull Requestを参照してください。
ONNX Runtimeパッケージの変更
InsightFaceでは、推論処理に「ONNX Runtime」が使用されています。
そのため、GPUで処理するためには、CPU版のパッケージ(onnxruntime
)からGPU版のパッケージ(onnxruntime-gpu
)に変更する必要がありました。
InsightFace自体は、既にGPU版のパッケージが考慮されているため、インストールするパッケージの変更だけで済みます。
ベースイメージの変更
Docker上でGPUを使用するため、NVIDIA Container Runtime(NVIDIA Docker)を使用しました。
それに伴い、CPU版ではDockerイメージのベースイメージとしてubuntu:20.04
を使用していましたが、GPU版ではnvidia/cuda:11.0.3-cudnn8-devel-ubuntu20.04
に変更しました。
汎用的(?)な「ベースイメージの探し方」は以下の通りです。
- ONNX Runtimeの「CUDA Execution Provider」ページを確認し、要件(CUDAバージョンなど)を調べる。
- DockerHubの「nvidia/cuda」からその要件を満たすDockerイメージを探す。
処理時間の測定
CPUからGPUに変更することで、処理時間がどう変化したのかを測定しました。
測定のため、顔検出サーバに処理時間の測定処理を追加しました。詳しくは以下のPull Requestを参照してください。
測定条件
処理時間の測定は、以下の条件で実施しました。
環境
以下の環境で顔検出サーバ(detector-insightface
)を動作させ、処理時間を測定しました。
- 環境1(CPU):
- MacBook Pro
- CPU: Intel Core i7 1068NG7 2.3GHz 4コア/8スレッド
- 環境2(CPU):
- 自作PC
- CPU: AMD Ryzen 7 3700X 3.6GHz 8コア/16スレッド
- 環境3(GPU):
- 自作PC
- CPU: AMD Ryzen 7 3700X 3.6GHz 8コア/16スレッド
- GPU: GeForce GTX 1070 8GB
- NVIDIAドライバ: 460.91.03
- CUDA: 11.0.3
コード
測定対象のコードとして、20210808a
タグのコードを使用しました。
画像ファイル
測定対象の画像ファイルとして、Gitリポジトリに同梱しているpakutaso_43730.jpg
(1人)、pakutaso_5574.jpg
(4人)を使用しました。
コマンド
測定には以下のコマンドを使用しました。
curl --silent \
--request POST \
--header "Content-Type: multipart/form-data" \
--form "file=@pakutaso_43730.jpg;type=image/jpeg" \
http://localhost:8000/detect \
| jq .response.detectionTimeInNanoseconds
curl --silent \
--request POST \
--header "Content-Type: multipart/form-data" \
--form "file=@pakutaso_5574.jpg;type=image/jpeg" \
http://localhost:8000/detect \
| jq .response.detectionTimeInNanoseconds
測定回数
測定は4回行い、1回目は破棄し、残り3回の平均値を結果としています。
測定結果
測定結果は以下の通りです。
環境 | CPU/GPU | pakutaso_43730.jpg |
pakutaso_5574.jpg |
---|---|---|---|
環境1 | CPU | 1,588 ミリ秒 | 5,177 ミリ秒 |
環境2 | CPU | 241 ミリ秒 | 687 ミリ秒 |
環境3 | GPU | 50 ミリ秒 | 152 ミリ秒 |
CPUが同じ「環境2」と「環境3」を比べてみると、4.5倍ほどの速度で動作している様です。劇的とまでは行かないにしろ、やはりGPUは早いですね。
また、検出される顔が増えると処理時間が増えることも確認できます。顔器官点検出、顔属性推定は顔毎に行われるので当然ですね。
CPUでも1秒あたり4フレーム、GPUだと20フレームを処理できるので、リアルタイムは難しいですが、多くのアプリケーションに適用できそうです。
最後に
今回はInsightFaceのGPUでの動作に挑戦してみました。結果として、拍子抜けするぐらいあっさり成功しました。
高速に顔検出できるようになったので、動画の処理にも挑戦したいと思っています。
Discussion