Open23

ONNXRuntime Unity Plugin

Koki IbukuroKoki Ibukuro

Unity BarracudaSentisに変わって迷走しているなか、別の選択肢を試して置くことは大事だなと思い

OnnxRuntimeをUnityで動かす実験をしてみます。

https://github.com/microsoft/onnxruntime/

Onnx自体がMicrosoft製ということもあり、C APIをC#から叩くコードは全部含まれていて、それとUnity側の世界を繋げてあげるあげるだけで動きそうな予感。うまく行けばWebでも同じコードで動くかもという淡い期待。

Koki IbukuroKoki Ibukuro

Onnx RuntimeはMicrosoft製というだけあり、C#のAPIが整備されていてクオリティも高いので、変な自作はせずにそのまま使いたい。その時に厄介になるのはのは、DllImportで定義されている#define

https://github.com/microsoft/onnxruntime/blob/49470f06e88ff99837e7ab0ae6062c32a782e068/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs#L519-L528

PlayerSettingsの Scripting Define Symbolsに入れれば動くと思わわれるかも知れないが、EditorでもAndroidやiOSが有効になるので、Editor実行時にも動作させるには、TensorFlow Liteで定義したようなUnity Editorを除外する処理を書かなくてはいけません。Onnx Runtime本家で対応してくれないかな…。

https://github.com/asus4/tf-lite-unity-sample/blob/7eb841ea486abce4837ecee0fbc30868a1efce70/Packages/com.github.asus4.tflite/Runtime/Interpreter.cs#L241-L247

本家にPR送ってみるのもありだけど、ひとまずUnityで実行出来るように、ビルド前に無理やりPlayerSettings.SetScriptingDefineSymbolsでdefineを書き換えるということをしてみた。一応動いている気はする。

https://github.com/asus4/onnxruntime-unity-examples/blob/f06b8bc3387dbe56c18c442e20004a4b828c524c/Packages/com.github.asus4.onnxruntime/Editor/OrtPreProcessBuild.cs#L19-L28

Koki IbukuroKoki Ibukuro

テストで入れた、軽量なImage classification model Apple MobileOne がmacOS, iOS, Androidで動いたので、とりあえず、Unity package方式でプレビューリリース。

他のプラットフォーム対応。GPU acceleration 対応。 などなどやることはまだまだ沢山あるが、ひとまず、Unity BarracudaやSentisで動かないようなOnnxモデルもUnityで動くなるのは喜ばしい限り。

https://github.com/asus4/onnxruntime-unity-examples/releases

UnityのWebカメラ入力をリサイズしてNCHW変換するところもCompute shader一発で行けたので、TensorFlow Liteでの知見が生きている。

Koki IbukuroKoki Ibukuro

Tokanizer等の面倒くさいpre/post processingも extensions という形でネイティブ実装されているみたい。便利!

Koki IbukuroKoki Ibukuro

Yoloxも動いた。macOS/iOS上のCoreMLは動くけど、AndroidのNNAPIではCPUにフォールバックされて遅い。でもCPUモードも十分速いですね。
次はextensions対応。

Koki IbukuroKoki Ibukuro

WindowsとLinux対応を追加中。

CPUのライブラリのサイズは小さいのだが、CUDAのGPU providerがそれぞれ300MB以上あり、全部を
GitHub LFSで管理するのも辛いなーと。


私のGitHub LFSの99%はTFLiteのためにお金払っている。こんなに使ってもらえると思わなかったので適当に全部入りにしてしまった…。

ということでお金の節約も考えて、最初からNPMだけにするかな。
はじめは全部をまとめてNPMにpublishしようとしたら、413 Content Too Largeで公開出来なかった。NPMの公式の最大ファイルサイズはちょっと見つからなかったけど。

選択肢として、NuGetへ移行することも調べたが、NuGetも最大ファイルサイズは250MBらしい。NuGetでも機械学習ライブラリを公開したいのに最大サイズが小さすぎと議論されていた。わかる。

なので、NPMのまま、WindowsとLinuxのGPU providerはCore packageから分割することにした。

Koki IbukuroKoki Ibukuro

Windows DirectX12で動くDirectML版はonnxruntime.dllに統合されていて、バイナリサイズも1MBくらいしか変わらないので、コアパッケージに入れてあげるのがいいかも知れないな。

UnityユーザーのWindowsにCUDAは入ってない可能性高いので。

Koki IbukuroKoki Ibukuro

XNNPACK対応入れてみた。けど、テストに使ってるモデルがXNNPACK対応してないみたい?もっと単純なモデルで検証必要かな。

Koki IbukuroKoki Ibukuro

ONXX Runtime Extensions

https://onnxruntime.ai/docs/extensions/build.html
https://github.com/microsoft/onnxruntime-extensions/blob/main/build.sh

この辺を参考にmacOS Fat dylibをビルドしてみた。

cmake -D CMAKE_OSX_ARCHITECTURES=x86_64 "$@" ../../.. && cmake --build . --config $BUILD_FLAVOR  --parallel "${CPU_NUMBER}"

cmake -D CMAKE_OSX_ARCHITECTURES=arm64 "$@" ../../.. && cmake --build . --config $BUILD_FLAVOR  --parallel "${CPU_NUMBER}"

でそれぞれビルドして最後に

lipo -create -output libortextensions.dylib path_to_x86_64//libortextensions.dylib path_to_arm64/libortextensions.dylib

で結合する。で合ってると思う、

Koki IbukuroKoki Ibukuro
Koki IbukuroKoki Ibukuro

ONXX 2GB超のモデルファイルの扱い

ONNXのファイルフォーマットは、ProtoBufに依存している。それの制約で、2GB超のファイルを扱えない。
Stable Diffusionなどの大きいモデルでは、

  • model.onnx
  • weights.pb

とファイルが分かれることがあるみたい。

  • model.onnx
  • model.onnx.data

となってるやつもある。これらをORTフォーマットに変換することは出来るのかな?
.onnx拡張子を取り扱うと、OnnxRuntimeプロジェクトでUnity Sentisをインストール出来なくなるため、.onnxではなく、*.ortだけのサポートにしたかったが。

調査中。

Koki IbukuroKoki Ibukuro

マルチプラットフォームで動作

  • Classification
  • Object Detection
  • Segmentation

という基本的なサンプルを追加。基本は完了した気がするので、閉じます。

Koki IbukuroKoki Ibukuro

OnnxRuntimeのバージョンを更新しようとしたらてっきり忘れていたので、再オープン。作業を残しておくほうが良さそう。

OnnxRuntime 1.19.2

Windowsのパッケージがzipからnupkgに変更されたくらいで問題なくアップデートできた。

OnnxRuntime Extensions 0.12.0

ビルド環境としてサポートされているORT versionが1.17.1までなのが不満だが、問題なくGitHub Actionsでのビルドもできた。

ORT-ExtensionsのAndroid用バイナリがダウンロードできていない事に気づいたので、それも修正した。

https://github.com/asus4/onnxruntime-unity/issues/25

Koki IbukuroKoki Ibukuro

OnnxRuntime v1.20.0 対応

https://github.com/microsoft/onnxruntime/releases/tag/v1.20.0

が出てたのでバージョンアップを試みたところ、ライブラリの更新は問題なく言ったのに、GitHub Actionでnpm publishが失敗するという現象。毎回、npm publish --dry-run が通るのを確認してから実行しているが、dry-runは通るのに、本番実行するとエラーという現象。

ログを確認すると、ファイルサイズが大きすぎるとのこと。

npm notice unpacked size: 674.5 MB
npm notice shasum: a68a74ffe9c4f600dedf7ce72da6b7d17b2a0a90
npm notice integrity: sha512-9xM4z3UwO+1Mv[...]m+IccHdYt5TIw==
npm notice total files: 15
npm notice
npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access
npm error code E413
npm error 413 Payload Too Large - PUT https://registry.npmjs.org/com.github.asus4.onnxruntime.win-x64-gpu - Payload Too Large
npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2024-11-21T13_20_26_678Z-debug-0.log
Error: Process completed with exit code 1.

npm公式でのファイルサイズ制限は確認できなかったのものの、Azure-devopsや、以前までうまく言っていたバージョンのファイルサイズを確認するに、npmには、単体ファイル500MBという制限があるみたい。 OnnxRuntime v1.20.0のリリースノートにCUDAパッケージに新しいdependenciesが追加とあるので、それでパッケージサイズが増えてしまったみたい。仕方ないのでCUDAのライブラリはnpmに公開することを諦めるしかないか…。とはいえ自分でOpenUPMの仕組みだと(幸運にももし人気がでてしまったときに)自分のGitHub LFSの通信料がかかるので、無料公開のライブラリとしてはなかなかつらい。

ひとまずGitHub Releaseにzipでおいて、手動ダウンロードしてもらう仕組みに帰るかな…。