版本:2022.3
语言:英语
作业依赖关系
Unity属性

并行作业

当您安排一个作业时,只能有一个作业执行一个任务。然而,有时您需要同时在许多对象上执行相同的操作。为此,请使用IJobParallelFor类型的ParallelFor作业,该类型继承自IJob。

ParallelFor作业使用一个作为其数据源的NativeArray数据。ParallelFor作业在多个CPU核心上运行。每个核心有一个作业,每个核心处理工作负载的一部分。

IJobParallelFor的行为类似于IJob,但它不是单个Execute方法,而是针对数据源中的每个项调用一次Execute方法。在方法Execute中,还有一个整数参数index,您可以在作业实现中使用它来访问和操作数据源的单个元素。

以下是一个ParallelFor作业定义的示例

struct IncrementByDeltaTimeJob: IJobParallelFor
{
    public NativeArray<float> values;
    public float deltaTime;

    public void Execute (int index)
    {
        float temp = values[index];
        temp += deltaTime;
        values[index] = temp;
    }
}

安排ParallelFor作业

要安排一个ParallelFor作业,您必须指定要分割的NativeArray数据源长度。当结构中有多个NativeArray时,作业系统不知道您想要将其用作数据源的哪个NativeArray。长度还告诉作业系统期望多少个Execute方法。

在Unity的原生代码中,ParallelFor作业的安排更复杂。当Unity安排一个ParallelFor作业时,作业系统将工作分割成批次以便在核心之间分配。每个批次包含一组Execute方法。作业系统然后在Unity的原生作业系统每个CPU核心中安排一个作业,并将该原生作业传递到批次以完成。

A ParallelFor job dividing batches across cores
ParallelFor作业在核心间分割批次

当一个原生作业比其他作业先完成其批次时,它会窃取其他原生作业剩余的批次。它一次只窃取一个原生作业剩余批次的一半,以确保缓存局部性

为了优化此过程,您需要指定一个批次计数。批次计数控制您将获得多少个作业,以及线程之间工作重新分配的粒度。具有较低的批次计数(如1),可在线程之间提供更均匀的工作分配。然而,它伴随着一些开销,因此有时增加批次计数会更好。从1开始,直到性能增益可忽略不计,这是一个好的策略。

以下是一个安排ParallelFor作业的示例

作业代码

// Job adding two floating point values together
public struct MyParallelJob : IJobParallelFor
{
    [ReadOnly]
    public NativeArray<float> a;
    [ReadOnly]
    public NativeArray<float> b;
    public NativeArray<float> result;

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

主线程代码

NativeArray<float> a = new NativeArray<float>(2, Allocator.TempJob);

NativeArray<float> b = new NativeArray<float>(2, Allocator.TempJob);

NativeArray<float> result = new NativeArray<float>(2, Allocator.TempJob);

a[0] = 1.1;
b[0] = 2.2;
a[1] = 3.3;
b[1] = 4.4;

MyParallelJob jobData = new MyParallelJob();
jobData.a = a;  
jobData.b = b;
jobData.result = result;

// Schedule the job with one Execute per index in the results array and only 1 item per processing batch
JobHandle handle = jobData.Schedule(result.Length, 1);

// Wait for the job to complete
handle.Complete();

// Free the memory allocated by the arrays
a.Dispose();
b.Dispose();
result.Dispose();

ParallelForTransform作业

ParallelForTransform作业是另一种专门为操作Transforms而设计的ParallelFor作业。它对于从作业中有效地执行Transform操作非常有用。有关更多信息,请参阅ParallelForTransform API文档。

作业依赖关系
Unity属性