Upgrade to Pro — share decks privately, control downloads, hide ads and more …

VRMSpringBoneをJobSystem&ECSで最適化してみた話

08a7d188d046f35b2501e686616f71bd?s=47 mao
February 19, 2019

 VRMSpringBoneをJobSystem&ECSで最適化してみた話

第1回 VRM勉強会 登壇資料
https://vrm.connpass.com/event/116985/

・ サンプルプロジェクト
https://github.com/mao-test-h/VRMSpringBone-Optimize

----------------------------------------------------------------------------
▼ 参考リンク集

・【GTMF2018TOKYO】ハードウェアの性能を活かす為の、Unityの新しい3つの機能
https://www.slideshare.net/UnityTechnologiesJapan/gtmf2018tokyounity3

・【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング
https://www.slideshare.net/UnityTechnologiesJapan/cedec2018cpu-entity-component-systemecs

・Memory Management of C# with Unity Native Collections
https://www.slideshare.net/neuecc/memory-management-of-c-with-unity-native-collections

08a7d188d046f35b2501e686616f71bd?s=128

mao

February 19, 2019
Tweet

Transcript

  1. 第1回 VRM勉強会
 VRMSpringBoneを
 JobSystem & ECSで
 最適化してみた話


  2. 自己紹介
 mao ( @TEST_H_ )
 
 ・ プログラマー


  3. ▼ 今回話す内容
 dwango/UniVRMにあるVRMSpringBone(とそれに関連する機能) をUnityの新機能であるJobSystemや ECS(EntityComponentSystem)を用いて最適化出来ないか検証し てみたお話。
 ※VRMSpringBone : モデルの服や髪といった揺れ物を制御する機能。
 


    → 何通りか検証してみたので、
   検証結果や効率化に関するTipsなどをご共有。

  4. ▼ 今回話す内容
 ※Unityエンジニア向けの内容です。
 ※実装に関する詳細な情報まではお話しない想定。
 → 詳細な設計周り/JobSystem基礎/ECS基礎/etc…
 
 今回話すのは実装概要(簡単な設計)、パフォーマンスの計測結 果、幾つかのTipsと言ったポイントまで。
 ※最後におまけとしてちょっとした補足や参考リンクを記載。


  5. ・ 資料は後日公開予定。
 ・ 実装したソースはGitHubにて公開済み。 mao-test-h/VRMSpringBone-Optimize


  6. ▼ 注意点
 ・ 実装には幾つかのPreviewな機能を使っている。
 - ECSとか、あとBurstCompilerは基本有効にしている。
 
 ・ 実装についてはまだまだ手探りな部分が多い状態。。
 -

    完全に理解できていないので、
    あくまで一例程度に留めて頂けると幸いです。。
 
 
 
 ※ちなみに全部プライベートでやっている趣味開発での検証内容。
  その為に実務導入を前提とした内容では無い事を一応追記。。

  7. ▼ 目次
  ▽ サンプルについて
  ▽ 実装内容とパフォーマンス
 - JobSystem (モデル毎に処理)
 -

    JobSystem (全モデル分を一括で処理)
 - ECS & JobSystem
 
  ▽ まとめ

  8. サンプルについて


  9. ▽ サンプルについて
 以下の環境にてニコニ立体ちゃんの VRMモデル256体を同時に動かして負 荷計測してみた。
 
 ・ 実行環境はStandalone(Windows) + IL2CPP

    
 - CPU : Intel Core i7-8700K
  (Worker Threadは11本)
 ・ Unity標準のProfilerで計測 
 ・ 途中でモデル1体を動的に追加/削除 
 

  10. ※ オリジナルの挙動について


  11. ※ オリジナルの挙動について


  12. ※ オリジナルの挙動について
 ・ MainThreadベースで処理されている
   LateUpdateの負荷が支配的。
 → 大体13ms~は掛かっている印象。
 
 ・

    動的なモデルの増減については
   そこまで負荷は高くない。

  13. None
  14. 実装1 : JobSystem
 (モデル毎に処理)


  15. ▽ JobSystem (モデル毎に処理)
 ・ モデル単位で「モデルが持つ全ての揺れ物対象のボーン」の
   情報を1箇所で管理。
 → こちらの集めたバッファを対象にJobを発行(Schedule)していく。
 


    → 物理演算を行うのと同時にTransformAcess経由で即時に更新。
 ※ Job(IJobParallelForTransform)の中でTransformの更新も行っている。
 
 ・ 今回の例で言うと、1モデルに付き必要な計算を行うJobが
   3つほど存在するので...「モデル256体 x 3つのJob」
 → 計763個のJobが発行されるイメージ

  16. ▼ データの簡易イメージ
 モデルが持つVRMSpringBone
 (髪、スカート、アクセサリーなど) 


  17. ▼ データの簡易イメージ
 モデルが持つVRMSpringBone
 (髪、スカート、アクセサリーなど) 
 Jobで使うデータ
 物理演算で使う値[] 
 Transform[]
 etc...


    ※Transformの配列はイメージ。正確に言うと「TransformAccessArray」を用いている。

  18. ▼ データの簡易イメージ
 モデルが持つVRMSpringBone
 (髪、スカート、アクセサリーなど) 
 Jobで使うデータ
 物理演算で使う値[] 
 Jobで行う処理
 ・コリジョンの算出


    ・親の回転値の取得
 ・物理演算/反映
 Transform[]
 etc...
 ※Transformの配列はイメージ。正確に言うと「TransformAccessArray」を用いている。

  19. ▼ データの簡易イメージ
 モデルが持つVRMSpringBone
 (髪、スカート、アクセサリーなど) 
 Jobで使うデータ
 物理演算で使う値[] 
 Jobで行う処理
 ・コリジョンの算出


    ・親の回転値の取得
 ・物理演算/反映
 Transform[]
 ・コリジョンの算出
 ・親の回転値の取得
 ・物理演算/反映
 ※モデル単位でデータが纏めれてJobの発行が行われる。
 etc...
 物理演算で使う値[] 
 Transform[]
 etc...

  20. ▽ JobSystem (モデル毎に処理)


  21. ▽ JobSystem (モデル毎に処理)


  22. ▽ JobSystem (モデル毎に処理)
 MainThreadの処理は5ms以内には収まった。
 ※但したまにスパイクがチラホラと...


  23. ▽ 結果
 ・ この結果だけ見るとマシにはなったけど....
   モデル毎にJobを発行している影響か、
   WorkerThreadの処理の並びが疎ら...。
 → もっと詰められないか?


    
 ・ 動的なモデルの増減については
  データがモデル単位で別れているためか、
  そこまで負荷は高くない印象。
 (スパイクは別の要因で発生している物)

  24. 実装2 : JobSystem
 (全モデル分を一括で処理)


  25. ▽ JobSystem (全モデル分を一括で処理)
 ・ 揺れ物対象のボーンをモデル単位ではなく
   全モデル分の情報を一箇所に纏めた上で処理。
 → こちらの集めたバッファを対象にJobを発行していく。
 


    
 全てのデータを1箇所で集中管理しているので
 発行されるJobは3つのみ。
 ※先程のやり方だと763回発行されていたので回数に大きな差。
  但しJobが処理するデータ数はその分増えているイメージ。

  26. ▼ データの簡易イメージ
 モデルが持つVRMSpringBone
 (髪、スカート、アクセサリーなど) 
 Jobで使うデータ
 Jobで行う処理
 ・コリジョンの算出
 ・親の回転値の取得
 ・物理演算/反映


    ※全モデルのデータが1箇所に纏めれてJobの発行が行われる。
 物理演算で使う値[] 
 Transform[]
 etc...

  27. ▽ JobSystem (全モデル分を一括で処理)


  28. ▽ JobSystem (全モデル分を一括で処理)


  29. ▽ JobSystem (全モデル分を一括で処理)
 MainThreadの負荷が0.3ms~ぐらいに。
 →トータルで見ても0.8~1msぐらいな印象。
 
 ※ 但し...動的なモデルの増減については...
 次回 、「パフォーマンス死す」デュエルスタンバイ!


  30. ▽ JobSystem (全モデル分を一括で処理)


  31. ▽ JobSystem (全モデル分を一括で処理)


  32. ▽ JobSystem (全モデル分を一括で処理)
 動的なモデルの増減が重い。
 → 追加/削除周りで20ms~は掛かっている感...


  33. ▽ 結果
 ・ 処理速度自体は今回挙げた例の中で一番良い結果となった
 
 → データが揃っているのでJobの発行の負担も少なく、バッチ処理が効いている。
 
 
 ・

    但し動的なモデルの追加/削除における負荷はそれなり...
 
 → 理由としては単純で一箇所で管理しているバッファの再構築。
   ※ もう少し軽減できないかな...と思ったり(要検証)

  34. 実装3 : ECS & JobSystem


  35. ▽ ECS & JobSystem
 ・ 先に結論から言うと既存のSpringBoneがGameObjectと
   密接に関わってくるためにHybridベースにする必要があり、
   データの効率化が出来ていないという点で言えば


      ECSでなくても良い感良い感はあったり。。
 
 ※ ECS自体はその性質上、「意識せずともデータが纏められる上でComponentSystem側で効率よく バッチ処理を行える」「データの動的な増減自体も低コスト」というパフォーマンス的な利点があり、先 程の例で言うとデータの集中管理に近いことを意識せずに行うことが出来るのだが...。 
 Hybrid故の負荷が...(後述)

  36. ▽ ECS & JobSystem
 ・ 今回の実装例で言うと、正直先程挙げた
   JobSystemベース(集中管理型)でも十分感あるが、
   実装検証自体は出来ているので参考値としてご共有まで。


    
 ・ 設計周りについては長くなりそうなので割愛...。
 → やっている事は先程のデータの集中管理に近い。
   (データを一箇所で纏めて一気に処理していく的な)

  37. ▽ ECS & JobSystem


  38. ▽ ECS & JobSystem


  39. ▽ ECS & JobSystem
 MainThreadの負荷は0.15ms~ぐらい。
  ※ECSに分離したことで他のLateUpdateの負荷が無くなっている。 
 
 → トータルで見ても1~2msぐらいな印象。


    
 ※ちなみに...動的なモデルの増減については...

  40. ▽ ECS & JobSystem


  41. ▽ ECS & JobSystem
 DirtyTransformAccessArrayUpdate


  42. ▽ ECS & JobSystem
 再構築を行うデータが減っているので
 マシにはなっているがそれでも若干高い
 → 追加/削除周りで10~15msは掛かっている感...


  43. ▽ 結果
 ・ 増減の負荷はJobベースのやつと比べると少しマシに
 
 → それでもDirtyTransformAcecssArrayUpdate周りと言った
   データの再構築が負荷として残っている。
 


    
 ・ あくまで現時点の機能で実装した一例でしかないので
   将来的な変更によっては効率化出来るかもしれない。
   (希望的観測)
 → GameObjectがUnityEngine.Transformに依存しない構造になってくれるとか。 そのうちガンにも効くようになるかもしれない。

  44. まとめ


  45. ・ JobSystemベースに関しては、
   状況に応じて使っていけそうな印象。
 → 但し一部PreviewPackageを用いているので注意。
 
 ・ ECSについては将来的な変更も含めて
  

    現時点では何とも言えないところがある。(要検証)
 → 完全なHybridベースの実装だとどうなるのか?
 → 将来的なGameObjectのデータの持ち方はどうなるのか?
 まとめ

  46. 後は今回の実装例についてはモデル256体を同時に動かすという 負荷テストを前提とした計測結果なので、実際に使う際にはオリジ ナルの挙動含め、要件の規模に合わせて使い分けていけば良い かと思われる。
 まとめ


  47. END


  48. ・ ECS & JobSystemについて
 
 - 【GTMF2018TOKYO】ハードウェアの性能を活かす為の、Unityの新しい3つの機能 
 
 -

    【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラ ミング
 
 ・ メモリとか
 
 - Memory Management of C# with Unity Native Collections 
 おまけ : 参考リンク集