当您安排一个作业时,只能有一个作业执行一个任务。然而,有时您需要同时在许多对象上执行相同的操作。为此,请使用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
作业,您必须指定要分割的NativeArray
数据源长度。当结构中有多个NativeArray
时,作业系统不知道您想要将其用作数据源的哪个NativeArray
。长度还告诉作业系统期望多少个Execute
方法。
在Unity的原生代码中,ParallelFor
作业的安排更复杂。当Unity安排一个ParallelFor
作业时,作业系统将工作分割成批次以便在核心之间分配。每个批次包含一组Execute
方法。作业系统然后在Unity的原生作业系统每个CPU核心中安排一个作业,并将该原生作业传递到批次以完成。
当一个原生作业比其他作业先完成其批次时,它会窃取其他原生作业剩余的批次。它一次只窃取一个原生作业剩余批次的一半,以确保缓存局部性。
为了优化此过程,您需要指定一个批次计数。批次计数控制您将获得多少个作业,以及线程之间工作重新分配的粒度。具有较低的批次计数(如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
作业是另一种专门为操作Transforms而设计的ParallelFor
作业。它对于从作业中有效地执行Transform操作非常有用。有关更多信息,请参阅ParallelForTransform API文档。