Version: Unity 6.0 (6000.0)
语言 : 中文
作业依赖关系
Thread safe types

并行作业

调度作业时,一项作业只能执行一个任务。但有时您需要对许多对象执行相同的操作。为此,请使用从 IJobParallelFor 继承的 ParallelFor 作业类型。

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

IJobParallelFor 的行为方式类似于 IJob,但它用的不是单个 Execute 方法,而是在数据源中逐项调用一次 Execute 方法。Execute 方法中还有一个整数参数索引,可用于访问并操作作业实现中数据源的单个元素。

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,那么作业系统将无法确定要将哪一个作为数据源。长度还能让作业系统知道应该存在多少个 Execute 方法。

在 Unity 的原生代码中,ParallelFor 作业的调度更为复杂。Unity 在调度 ParallelFor 作业时,作业系统会将工作分成多个批次,以便将任务分配到多个核心。每个批次都包含一部分的 Execute 方法。然后,作业系统会为每个 CPU 核心安排一项 Unity 原生作业系统中的作业,并将该原生作业传递给批次以供完成。

ParallelFor 作业将批次划分给各内核
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 作业是另一种专门针对变换进行操作而设计的 ParallelFor 作业。这种作业有助于高效地处理作业中的变换操作。

其他资源

作业依赖关系
Thread safe types