ONNXRuntime Unity Plugin
Barracudaを使わないOnnxネイティブプラグイン。こちらのリポジトリで開発中です↓
Unity BarracudaがSentisに変わって迷走しているなか、別の選択肢を試して置くことは大事だなと思い
OnnxRuntimeをUnityで動かす実験をしてみます。
Onnx自体がMicrosoft製ということもあり、C APIをC#から叩くコードは全部含まれていて、それとUnity側の世界を繋げてあげるあげるだけで動きそうな予感。うまく行けばWebでも同じコードで動くかもという淡い期待。
それとStable Diffusion系も豊富にONNXモデルに変換されていて、Onnx Runtimeでも動くといいなと。
pre processは HuggingFaceのDiffusersリポジトリが参考になりそう。
Onnx RuntimeはMicrosoft製というだけあり、C#のAPIが整備されていてクオリティも高いので、変な自作はせずにそのまま使いたい。その時に厄介になるのはのは、DllImportで定義されている#define
PlayerSettingsの Scripting Define Symbolsに入れれば動くと思わわれるかも知れないが、EditorでもAndroidやiOSが有効になるので、Editor実行時にも動作させるには、TensorFlow Liteで定義したようなUnity Editorを除外する処理を書かなくてはいけません。Onnx Runtime本家で対応してくれないかな…。
本家にPR送ってみるのもありだけど、ひとまずUnityで実行出来るように、ビルド前に無理やりPlayerSettings.SetScriptingDefineSymbolsでdefineを書き換えるということをしてみた。一応動いている気はする。
テストで入れた、軽量なImage classification model Apple MobileOne がmacOS, iOS, Androidで動いたので、とりあえず、Unity package方式でプレビューリリース。
他のプラットフォーム対応。GPU acceleration 対応。 などなどやることはまだまだ沢山あるが、ひとまず、Unity BarracudaやSentisで動かないようなOnnxモデルもUnityで動くなるのは喜ばしい限り。
UnityのWebカメラ入力をリサイズしてNCHW変換するところもCompute shader一発で行けたので、TensorFlow Liteでの知見が生きている。
Tokanizer等の面倒くさいpre/post processingも extensions という形でネイティブ実装されているみたい。便利!
Yoloxも動いた。macOS/iOS上のCoreMLは動くけど、AndroidのNNAPIではCPUにフォールバックされて遅い。でもCPUモードも十分速いですね。
次はextensions対応。
解説記事書いた。
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から分割することにした。
Windows DirectX12で動くDirectML版はonnxruntime.dllに統合されていて、バイナリサイズも1MBくらいしか変わらないので、コアパッケージに入れてあげるのがいいかも知れないな。
UnityユーザーのWindowsにCUDAは入ってない可能性高いので。
XNNPACK対応入れてみた。けど、テストに使ってるモデルがXNNPACK対応してないみたい?もっと単純なモデルで検証必要かな。
Add operatorだけの単純なモデルで単体テストを作った。
ONXX Runtime Extensions
この辺を参考に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
で結合する。で合ってると思う、
違った。Cmakeは
CMAKE_OSX_ARCHITECTURES="arm64;x86_64"
を指定するだけで、Fat バイナリを生成できるようになっていた。
最終的に、macOS, Windows, LinuxをGitHub Actionsでビルド出来るようになった。
Stable Diffusion
Hugging FaceのOrtドキュメント
ONNX RuntimeのSDXLデモ
Onnx C#でのチュートリアル
複数のORTモデルの重ね合わせ技で結構難しそう。
チュートリアルのブログみてるけど、pythonの移植だけど、LINQの無駄多すぎだしちょっと別のものを検討するのがよいかも?
こっちのほうが良さげ?
Mediumにも解説書いた。
ONXX 2GB超のモデルファイルの扱い
ONNXのファイルフォーマットは、ProtoBufに依存している。それの制約で、2GB超のファイルを扱えない。
Stable Diffusionなどの大きいモデルでは、
- model.onnx
- weights.pb
とファイルが分かれることがあるみたい。
- model.onnx
- model.onnx.data
となってるやつもある。これらをORTフォーマットに変換することは出来るのかな?
.onnx拡張子を取り扱うと、OnnxRuntimeプロジェクトでUnity Sentisをインストール出来なくなるため、.onnxではなく、*.ortだけのサポートにしたかったが。
調査中。
Unity のPackage Managerからみるパッケージの見た目を整える作業。
公式ドキュメント
このリポジトリが参考になった。
このJetsonリポジトリが、いい感じにローカルで動きそうな、かつ面白い事例が集まっている。
マルチプラットフォームで動作
- Classification
- Object Detection
- Segmentation
という基本的なサンプルを追加。基本は完了した気がするので、閉じます。