Version: 2021.3
言語: 日本語
ParallelForTransform ジョブ
マルチプレイヤーとネットワーク

C# ジョブシステムのヒントとトラブルシューティング

Unity C# Job System を使用する場合は、以下を確認してください。

ジョブから静的データにアクセスしない

ジョブから静的データにアクセスすると、すべての安全システムが回避されます。誤ったデータにアクセスすると Unity をクラッシュさせることがあり、多くの場合予期せぬことが起こります。例えば、MonoBehaviour にアクセスすると、ドメインのリロード時にクラッシュする可能性があります。

注意 このリスクのため、今後のバージョンの Unity では 静的コード分析 を使用して、ジョブからグローバル変数へのアクセスを禁止します。もし、ジョブ内の静的データにアクセスすると、今後のバージョンの Unity では、コードが壊れることが予想されます。 

スケジュールされたバッチをフラッシュする

ジョブの実行を始めたい場合は、スケジュールされたバッチを JobHandle.ScheduleBatchedJobs でフラッシュします。このメソッドを呼び出すとパフォーマンスに悪影響を与える可能性があることに注意してください。バッチをフラッシュしないと、メイン (制御) スレッドが結果を待つまでスケジュールが遅延します。それ以外の場合は、JobHandle.Complete を使用して実行プロセスを開始します。

ノート: Entity Component System (ECS) では、バッチは暗黙のうちにフラッシュされるため、JobHandle.ScheduleBatchedJobs を呼び出す必要はありません。

NativeContainer のコンテンツを更新しない

参照戻り値 (ref return) がないため、直接 NativeContainer のコンテンツを変更することはできません。例えば、nativeArray[0]++;var temp = nativeArray[0]; temp++; と書くのと同じです。 これは nativeArray の値を更新しません。

代わりに、インデックスのデータからローカルの一時的なコピーを作成し、そのコピーを変更して、それを元のデータに保存する必要があります。以下のように行ないます。

MyStruct temp = myNativeArray[i];
temp.memberVariable = 0;
myNativeArray[i] = temp;

所有権を回復するには JobHandle.Complete を呼び出す

データの所有権を追跡するには、制御スレッドがそれらを再度使用する前に、依存関係を完了させる必要があります。 JobHandle.IsCompleted を確認するだけでは不十分です。制御スレッドへ NativeContainer タイプの所有権を取り戻すには、JobHandle.Complete メソッドを呼び出す必要があります。Complete を呼び出すと、安全システムの状態もクリーンアップされます。それを行わないと、メモリリークが発生します。この処理は、すべてのフレームに、前のフレームのジョブに依存関係のあるジョブをスケジュールする場合にも適用されます。

Schedule と Complete は制御スレッドで使う

ScheduleComplete は同じ制御スレッドからのみ呼び出すことができます。1 つのジョブが別のジョブに依存している場合はジョブ内にジョブをスケジュールしようとせず、むしろ JobHandle を使用して依存関係を管理します。

Schedule と Complete を適切なタイミングで完了する

ジョブが必要とするデータを取得したらすぐに、ジョブの Schedule を呼び出し、結果が必要になるまでそのジョブで Complete を呼び出してはいけません。実行中の他のジョブと競合していないときに、待機する必要のないジョブをスケジュールすることは適正な方法です。例えば、1 つのフレームの終了から次のフレームの開始までの間でジョブが実行されておらず、1 フレームの待ち時間が許容できる場合は、フレームの最後にジョブをスケジュールし、その結果を次のフレームで使用します。また、ゲームの切り替え部分が他のジョブで飽和状態であるのに、フレーム内の他のどこかで過度にジョブの少ない部分がある場合は、ジョブを少ない部分にスケジュールする方が効率的です。

NativeContainer タイプを読み取り専用にする

ジョブはデフォルトで NativeContainer タイプへの読み書きのアクセスを持っていることに注意してください。適時 [ReadOnly] 属性を使用して、パフォーマンスを向上させます。

データの依存関係を確認する

Unity の Profiler ウィンドウで、制御スレッドのマーカー “WaitForJobGroup” は、Unity がワーカースレッドのジョブを完了するのを待っていることを示しています。このマーカーは、解決する必要があるデータの依存関係がどこかに存在することを意味します。制御スレッドを強制的に待機させているデータの依存関係を追跡するには、JobHandle.Complete を探してください。

ジョブのデバッグ

ジョブには Run 関数があり、 Schedule の代わりに使用して制御スレッド上でジョブを即座に実行することができます。これはデバッグの目的で使用できます。

マネージメモリをジョブに割り当てない

マネージメモリをジョブに割り当てると非常に遅く、パフォーマンスを向上させるために Unity Burst コンパイラー を使用することはできません。Burst は作業をより簡単にする新しい LLVM ベースのバックエンドコンパイラー技術です。C# のジョブを処理し、高度に最適化されたマシンコードを生成し、プラットフォームの特定の機能を活用できます。

その他の情報


  • 2018–06–15 公開ページ

  • C# Job System は 2018.1 で公開NewIn20181

ParallelForTransform ジョブ
マルチプレイヤーとネットワーク