simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

Unity:C# JobSystemとBurstCompilerそしてECSこと(EntityComponentSystem)の概要

この三つがそろった時、Unity は完全体となって、Unreal は死ぬという噂が流れるほど
Unity のパフォーマンスを向上しつつ、競合状態などを起こさないように安全にコーディングできるようになるとのこと

さて、前回に続いて C# Job System の書式を学んでいます。以下のドキュメント読んでますが
github.com

そのドキュメントにまずは次の動画を事前に見ろ!(意訳)ってありましたので、見ました。
www.youtube.com

内容をざっくりまとめると

1.C# Job System の書式解説
具体的には、NativeArray をはじめ、NativeList, NativeSlice, NativeHashmap, NativeMultiHashmap, NativeMultiHashmap.ConcurentWriter など
みんなが C# でよく使ってきた List, Dictionary に相当するものを unsafe に扱えるものを C# 用に用意したよというもの(すごい、Unity 以外でも欲しい)
そのほか Job として何らかの C# コードを実行するには IJob を継承する struct を定義して Execute に処理書けば動くよ
普通はマルチスレッドに分散するよね、そんなときは IJob の代わりに IJobParallelFor を使うよ
超重要なことだけど、依存関係は Job の Schedule を切ったときに取得できる JobHandle を利用することで、安全に順番に Job を実行できるよ
お魚の群れのシミュレーションコードも、ここまで解説した基本の通りになっているよ

2.BurstComplier (C# Job Compiler)の使い方
まず速くなるのは

No virtual functions
No reference types
No GC
Native Containers
SIMD auto -vectorization
Preciton control (Low, Med, High)

の強い制約をもって最適化するためです
Compiler の恩恵を受けたければ、先ほど紹介した Job 構造体の attribute 宣言に
[ComputeJobOptimizationAttribute(Accuracy.Med, Support.Relaxed)]
を書くだけ(会場から笑い)

3.これまでの書式からの書き換えの簡単さの紹介
パフォーマンス気にしているなら Update を MonoBehavior ごとに書かずに、どっかにまとめて for 文を回すようにしてきたと思います。
みなさんそうしてます?(会場:はーい)クールだね
そんなギミックコードの Update 内の処理を Job の Execute に置き換えるだけで、ほら、既存のコードの高速化も超導入しやすいでしょう?(拍手)

4.ECS(EntityComponentSystem)
みんなが今まで書いてきたコンポーネント指向のコードは

GetComponent<Transform>()

といった形でメモリのあちこちから参照を引っ張ってきて、コンピュータは最適化に困っていたわけです。
解決するために ECS の書式に書き換える必要があるわけですが
具体的にはデータだけが定義されているような MonoBehavior は IComponentData を継承する struct に差し替えましょう
出現しているゲームオブジェクトをまとめて処理していたようなクラスは ComponentSystem を継承するクラスに差し替えて

List<Transform>

フィールドは

[InjectTuples]
public ComponentArray<Transform>

に書き換えて、C++でいうところのポインタ配列にして、連続でメモリアクセスできる状態にするのです。
ComponentSystemクラスの属性に
[UpdateAfter(typeof(DamageSystem))]
といった形で、さらに別の ComponentSystem との依存関係を定義できます。
驚いてほしいのはここから、ComponentSystem を JobComponentSystem に書き換えておけば OnUpdate 処理にて Job を作成し
AddDependency(job.Schedule(m_transforms, GetDependency()));
と書けば、C# Job System の書式説明で書いた Complete を呼ばなきゃ、みたなこともなく競合が起きなくなるし、これが最適化処理に響いて極めて高速化するわけ。
イメージとしては低レベルレイヤーですべての会話が成り立つという感じで、コードは競合状態を気にせず値変更とか書けるようになる!(会場:すごーい拍手)ハッピー

5.質疑応答
ネイティブ同士の会話は聞き取れないー

1時間の動画だけど、C# Job System, Burst Compiler, ECS などのキーワードと実装イメージの連絡を行いたいときは、こちらの動画をじっくり視聴することをオススメされるのもわかる気がした

さーて、サンプルコード読んでいくぞー
今なら読める気がする