TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

ONNX Runtimeを使ってみる その2(性能測定)

先日、ONNX Runtimeを使って、MNISTの推論を試した。

今回は、dlshogiのResnet 10ブロック、192フィルタのモデルを使って、GPUで実行した場合の速度と、CPUで実行した場合の速度を比較した。

測定条件

GPUでのONNXの推論にはTensorRT(FP16)を使用する。
CPUの測定にはONNX Runtimeを使用し、デフォルトのCPUプロバイダと、MKL-MLを有効にしたCPUプロバイダ、DNNLプロバイダのそれぞれで測定した。

OSはWindows 10 64bit、GPUGeForce 2080Ti、CPUはCore i7-6700K(4コア、8スレッド、4GHz)を使用した。

推論の対象は、floodgateの棋譜からサンプリングした1万局面、バッチサイズは128とした。
それぞれの条件で、3回測定し、その平均時間を求める。

GPUで実行した場合の速度

条件 平均処理時間
GPU(TensorRT) 0.3秒

デフォルトCPUプロバイダ

NuGetでビルド済みバイナリが提供されているので、Microsoft.ML.OnnxRuntimeをインストールして使用した。

条件 平均処理時間
CPU(デフォルト) 32.6秒

GPUよりも、106.7倍遅い。

CPU使用率は、ほぼ100%で張り付いている。
f:id:TadaoYamaoka:20200606183918p:plain

なお、NuGetで取得できるCPUプロバイダはOpenMPが有効になっているので、スレッド数は自動で調整されている。

グラフ最適化のオプションを設定してみたが、変わらなかった。

session_options.SetGraphOptimizationLevel(ORT_ENABLE_ALL);

ORT_DISABLE_ALLにすると2倍くらい遅くなったため、デフォルトでグラフの最適化は有効になっているようだ。

MKL-MLを有効にしたCPUプロバイダ

NuGetから取得できるので、Microsoft.ML.OnnxRuntime.MKLMLをインストールして使用した。

条件 平均処理時間
CPU(MKL-ML) 37.5秒

デフォルトのCPUプロバイダより遅くなっている。

CPU使用率は、余裕が残っている。
f:id:TadaoYamaoka:20200606184158p:plain

CPUを使い切っていないので、スレッド数を明示的に設定してみた。

session_options.SetIntraOpNumThreads(8);

すると、CPU使用率は100%近くになった。
f:id:TadaoYamaoka:20200606184514p:plain

処理時間は、

条件 平均処理時間
CPU(MKL-ML、スレッド8) 31.3秒

となり、デフォルトCPUプロバイダより速くなった。

MKL-MLの場合は、スレッド数を調整した方が速くなる場合があるようだ。

なお、ONNX Runtimeのスレッド数の設定には、SetInterOpNumThreadsとSetIntraOpNumThreadsがあるが、前者はグラフ全体のスレッド数、後者はノード内の実行を並列化する際のスレッド数を設定する。
参考:https://github.com/microsoft/onnxruntime/issues/2177
SetInterOpNumThreadsの方も8に変えてみたが、処理時間に変化はなかった。

DNNLプロバイダ

ビルド済みバイナリが提供されていないため、ソースからビルドした。
スタートメニューから「x64 Native Tools Command Prompt for VS 2019」を起動して、GitHubのレポジトリをcloneして以下のようにビルドする。

git clone --recursive https://github.com/Microsoft/onnxruntime
cd onnxruntime
.\build.bat --config RelWithDebInfo --build_shared_lib --parallel --use_dnnl --cmake_generator "Visual Studio 16 2019"

「build\Windows\RelWithDebInfo\RelWithDebInfo」にビルド済みライブラリができる。

DNNLプロバイダを有効にするには、

#include <dnnl_provider_factory.h>

OrtSessionOptionsAppendExecutionProvider_Dnnl(session_options, 1);

のように、ソースコードでプロバイダを追加する処理が必要になる。

処理時間は、

条件 平均処理時間
CPU(DNNL) 35.0秒

となり、スレッド数を調整したMKL-MLよりも遅い。

CPU使用率は、ほぼ100%になっている。
f:id:TadaoYamaoka:20200606185652p:plain

まとめ

ONNX Runtimeを使用して、CPUでdlshogiのモデルの推論を行った。
GPUと比較した場合、100倍以上遅くdlshogiをCPUで実行しても、とりあえず動かせる程度で強さは期待できなそうだ。

CPUのプロバイダの比較では、MKL-MLを有効にしたプロバイダが一番速かった。
ただし、デフォルトの設定ではCPUを使い切らないため、スレッド数を調整する必要がある。


測定に使用したソースは以下の場所にある。
DeepLearningShogi/onnx_benchmark.cpp at feature/onnx_runtime · TadaoYamaoka/DeepLearningShogi · GitHub