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

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

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

mao

February 19, 2019
Tweet

More Decks by mao

Other Decks in Technology

Transcript

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

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

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

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

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

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

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


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

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


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

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


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

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


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

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


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

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

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

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


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

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


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

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


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

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

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

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

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