ジョブのスケジュール
ParallelFor ジョブ

JobHandle と依存関係

ジョブの Schedule メソッドを呼び出すと、JobHandle を返します。コード内で JobHandle を他のジョブの依存関係として使用することができます。ジョブが別のジョブの結果に依存している場合は、以下のように、最初のジョブの JobHandle をパラメーターとして Schedule メソッドに渡すことができます。

JobHandle firstJobHandle = firstJob.Schedule();
secondJob.Schedule(firstJobHandle);

依存関係の合同

ジョブに多くの依存関係がある場合は、JobHandle.CombineDependencies メソッドを使用してそれらを合同できます。CombineDependencies を使うと、依存関係を Schedule メソッドに渡すことが可能です。

NativeArray<JobHandle> handles = new NativeArray<JobHandle>(numJobs, Allocator.TempJob);

// `handles` に複数のスケジュールされたジョブの `JobHandles` を割り当てます...

JobHandle jh = JobHandle.CombineDependencies(handles);

メインスレッドのジョブの待機

JobHandle を使用すると、ジョブの実行が終了するまでメインスレッドのコードを実行するのを強制的に待機させることができます。これを行うには、JobHandle のメソッド Complete を呼び出します。この時点で、メインスレッドは、ジョブが使っていた NativeContainer に安全にアクセスできます。

注意 ジョブをスケジュールすると、そのままでは実行を開始しません。スケジュールされたジョブがメインスレッドで待機しているときに、ジョブが使用している NativeContainer データにメインスレッドからアクセスする必要がある場合は、JobHandle.Complete メソッドを呼び出します。このメソッドはメモリキャッシュからジョブをフラッシュし、実行のプロセスを開始します。JobHandleComplete を呼び出すと、そのジョブの NativeContainer タイプの所有権をメインスレッドに返還します。これらの NativeContainer タイプにメインスレッドから安全にアクセスするには、JobHandleComplete を呼び出す必要があります。ジョブの依存関係の JobHandleComplete を呼び出すことで、所有権をメインスレッドに返還することも可能です。例えば、 jobAComplete を呼び出すこともできますし、jobA に依存する jobBComplete を呼び出すこともできます。どちらの場合でも Complete の呼び出し後に、jobA が使用していた NativeContainer タイプに、メインスレッドから安全にアクセス可能になります。

あるいは、データへのアクセスが必要ない場合は、バッチを明示的にフラッシュする必要があります。これを行うには、静的メソッド JobHandle.ScheduleBatchedJobs を呼び出します。このメソッドを呼び出すとパフォーマンスに悪影響を与える可能性があることに注意してください。

複数のジョブと依存関係の例

ジョブコードサンプル

//  2 つの浮動小数点の値を加算するジョブ
public struct MyJob : IJob
{
    public float a;
    public float b;
    public NativeArray<float> result;

    public void Execute()
    {
        result[0] = a + b;
    }
}

// 1 を値に加算するジョブ
public struct AddOneJob : IJob
{
    public NativeArray<float> result;
    
    public void Execute()
    {
        result[0] = result[0] + 1;
    }
}

メインスレッドコードサンプル

//結果を保存するために、1 つの float 値を格納できるネイティブの配列を作成します。この例では、説明のためにジョブが完了するのを待ちます。
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

//ジョブ1 のデータを設定します
MyJob jobData = new MyJob();
jobData.a = 10;
jobData.b = 10;
jobData.result = result;

//ジョブ1 をスケジュールします
JobHandle handle = jobData.Schedule();

// ジョブ2 のデータを設定します
AddOneJob incJobData = new AddOneJob();
incJobData.result = result;

// ジョブ2 をスケジュールします
JobHandle secondHandle = incJobData.Schedule(firstHandle);

//ジョブ2 が完了するのを待ちます
secondHandle.Complete();

//NativeArray のすべてのコピーが同じメモリを指している場合は、自分の NativeArray のコピーの結果にアクセスできます
float aPlusB = result [0];

//結果の配列に割り当てられたメモリを解放します
result.Dispose();

  • 2018–06–15 編集レビュー を行ってパブリッシュされたページ

  • C# Job System は 2018.1 で公開NewIn20181

ジョブのスケジュール
ParallelFor ジョブ