TadaoYamaokaの日記

山岡忠夫Homeで公開しているプログラムの開発ネタを中心に書いていきます。

ONNX Runtimeを使ってみる その3(DirectML)

ONNX RuntimeでDirectMLを使ってdlshogiのモデルの推論を行い、処理時間を比較してみた。

DirectMLを使えばAMDGPUでも推論が実行できるようになる。

DirectMLプロバイダの使用

NuGetからビルド済みバイナリが取得できる。
Microsoft.ML.OnnxRuntime.DirectMLをインストールする。

DirectMLプロバイダを使用するにはソースに以下の行を追加する。

#include <dml_provider_factory.h>

	session_options.DisableMemPattern();
	session_options.SetExecutionMode(ORT_SEQUENTIAL);
	OrtSessionOptionsAppendExecutionProvider_DML(session_options, 0);

DisableMemPattern()とSetExecutionMode(ORT_SEQUENTIAL)が必要である点は、
https://github.com/microsoft/onnxruntime/blob/master/docs/execution_providers/DirectML-ExecutionProvider.md
に記載されている。
この記述がないとSessionの初期化でエラーが発生する。

これで、ビルドは通るが実行にOrtSessionOptionsAppendExecutionProvider_DMLでメモリアクセス違反のエラーになった。

issuesを調べたところ同様のエラーの報告があり、対処方法が記載されていた。
https://github.com/microsoft/onnxruntime/issues/3360

ONNX Runtimeが使用するDirectML.dllは、Windows 10のシステムにインストールされているdirectml.dllと互換性がないため発生するようだ。
PATHに設定していても、システムフォルダが優先されるため、DirectML.dllを.exeのあるフォルダにコピーする必要がある。

onnxruntime.dllはちゃんと.exeのフォルダにコピーされるので、NuGetのパッケージの不備ではないかと思うが、「packages\Microsoft.ML.OnnxRuntime.DirectML.1.3.0\runtimes\win-x64\native\DirectML.dll」を手動でコピーした。
自動化するならVisual Studioのプロジェクトのビルド後の処理に設定するのが良いだろう。

処理時間測定

処理時間の測定結果は以下のようになった。
測定条件は、前回の記事と同じ。

比較のために、TensorRTとCPU(MKL-ML、スレッド数8)の結果も記載する。

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

TensorRTと比較すると、4.7倍遅くなっている。
TensorRTはTensorCoreを使いFP16で処理しているので、その違いがでていると思われる。

CPUと比較すると22.6倍速く、DirectMLを使用した方が速い。

まとめ

ONNX RuntimeのDirectMLプロバイダを使うことで、AMDGPUでも推論が動かせるようになる。
処理速度は、TensorRTには劣る(4.7倍遅い)が、CPUよりは断然に速い(22.6倍速い)。