0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VisualStudio C++ ONNXRUNTIME GPU(CUDA)でONNX初期化エラーが出る時

Last updated at Posted at 2024-12-25

NuGetで導入しているONNXRUNTIME-GPU(CUDA)を利用したいが、初期化でエラーが出てなんか遅い!

VisualStudio2022 C++でONNXRUNTIME(以下ORT)を利用したWindowsアプリ作ろうとしています。
VisualStudioでORTを利用するにはNuGetで導入すれば良さそうということはわかったのですが、CPUでの推論はともかく、CUDAがどうもちゃんと動いてくれません。
実行時、コンソールでは次のエラーが表示されていました。

エラーメッセージ
Exception during initialization: D:\a\_work\1\s\onnxruntime\core\session\provider_bridge_ort.cc:1539 onnxruntime::ProviderLibrary::Get [ONNXRuntimeError] : 1 : FAIL : LoadLibrary failed with error 126 "" when trying to load "C:\Users\ユーザ名\source\repos\プロジェクト名\x64\Release\onnxruntime_providers_cuda.dll"

また、推論時間も合わせて評価していたのですが、1回目はともかく、2回目以降の推論もどうも早くなりませんでした。

アルェ・・?
session_run_time:1009
session_run_time:965
session_run_time:944
session_run_time:991
session_run_time:967
session_run_time:947
session_run_time:1032
session_run_time:952
session_run_time:960
session_run_time:964
session_run_time:952
create_session_time:341,load_image_preprocess_time:97,inference_time:1025,inference_times_10AVE:980

ONNXの初期化でエラーが出ているようですが、その後の推論は結果を見るとちゃんとできていそう。CPUでの推論よりは速いけど、CUDAの推論としては遅い、よね?せめて2回目以降はもっと早くなるんじゃないの・・・?

環境

Windows11 pro 23H2 64bit
Microsoft Visual Studio Community 2022 (64 ビット) - Current
Version 17.12.3
Microsoft.ML.OnnxRuntime 1.20.1(NuGet)
Microsoft.ML.OnnxRuntime.Gpu 1.20.1(NuGet)
CUDA 12.4 (参考:あまり関係ない)
cuDNN 9.1 (参考:あまり関係ない)
C++

結論:Build毎に、Microsoft.ML.OnnxRuntime.Gpuのdll、libをエラーのフォルダに上書きコピーする

VisualStudioはORT-CPUのお世話はせっせとしてくれますが、同じNuGetで取得しているORT-GPUのお世話は一切してくれないのです。
そのため、Buildが走る度にORT-CPUのdllはせっせとコピーしてくれますが、ORT-GPUは一切コピーしてくれません。
ORT-GPUで動作させたい時は、ORT-GPUのdllが必要ですが、buildすればORT-CPU版だけ上書きしてくれます。
そのため、onnxruntime.dllonnxruntime_providers_shared.dllはビルドが走る度にCPU版に上書きされています。
ORT-GPUで動作させるのに必要なDLLは、例えば以下にあります。
C:\Users\ユーザ名\source\repos\プロジェクト名\packages\Microsoft.ML.OnnxRuntime.Gpu.1.20.1\runtimes\win-x64\native
ここにあるonnxruntime.dllonnxruntime_providers_shared.dllonnxruntime_providers_cuda.dllonnxruntime.libonnxruntime_providers_shared.libonnxruntime_providers_shared.libを、
C:\Users\ユーザ名\source\repos\プロジェクト名\x64\Releaseにビルドの度に上書きコピーしましょう。
onnxruntime.dllonnxruntime_providers_shared.dllは、同名ですが、CPUとGPUではファイルは別物です。
tensorrtはたぶんなくても大丈夫です。

GPUフォルダのdll、libで上書きコピーして実行した時の実行結果

エラーはなくなり、2回目以降の処理速度も速くなっています。(入力テンソルが1280,1280なのでやや遅い)

上書き後
session_run_time:403
session_run_time:42
session_run_time:31
session_run_time:32
session_run_time:32
session_run_time:32
session_run_time:32
session_run_time:30
session_run_time:30
session_run_time:30
session_run_time:31
create_session_time:397,load_image_preprocess_time:78,inference_time:415,inference_times_10AVE:45

その他

  • プロジェクトのプロパティから、ビルド後のイベントでファイルのコピーをすると手間が減るかもしれません
  • またlibについては追加する依存ファイルに記載しておくと、コピーは不要かもしれません
  • じゃあNuGetでORT-GPUだけ導入したらいいんじゃない?とも思いましたが、ORT-GPUにはonnxruntime_cxx_api.hがないため、ORT-CPUもNuGetで導入が必要です
  • ORT-GPUでの事例ですが、ORT-DML(DirectML)などでも同じだと思います

まとめ

  • VisualStudioにはNuGetでORT-CPU、ORT-GPUを導入できて便利ですが、肝心のDLLは手動での上書きコピーになります
  • っていうかNugetでORT-GPUを導入しているなら、気を利かせてORT-GPUのフォルダからもコピーして欲しいところ(なぜここは手動なのか?
  • もしかするとVisualStudioのユーザーでは当たり前のことかもしれませんが、検索してもあまりドンピシャな記事が見つからなかったので、書き残していくものです

後日談(2025/01/07 追記)

ONNX-CUDAが遅かったのでTensorRTにしようと考えているのですが、他のGPU対応も兼ねてONNXRUNTIME-DirectMLをNuGetで入れて動かしてみたところ、私の環境ではDirectMLの方がCUDAより若干速かったです。
1280*1280にリサイズした動画から物体検出をしていますが、DirectMLが17FPSで、CUDAが15FPSでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?