在调度作业时,只能有一个作业正在执行一项任务。在游戏中,通常希望对大量对象执行相同的操作。有一个称为 IJobParallelFor 的单独作业类型可以处理此问题。
注意:“ParallelFor”作业是 Unity 中对于任何实现 IJobParallelFor
接口的结构的统称。
ParallelFor 作业使用一个数据 NativeArray 作为其数据源。ParallelFor 作业在多个核心上运行。每个核心有一个作业,每个作业处理一部分工作量。IJobParallelFor
的行为类似于 IJob
,但其并非调用单个 Execute 方法,而是对数据源中的每一项都调用一次 Execute
方法。Execute
方法中有一个整数参数。该索引用于访问和操作作业实现中的数据源的单个元素。
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
,Unity C# 作业系统无法知道您希望将哪个用作数据源。长度还告诉 C# 作业系统应该有多少个 Execute
方法。
在后台,ParallelFor 作业的调度更加复杂。在调度 ParallelFor 作业时,C# 作业系统将工作分成多个批次以便在多个核心之间分配任务。每个批次包含一小部分 Execute
方法。然后,针对每个 CPU 核心,C# 作业系统会在 Unity 本机作业系统中调度最多一个作业,并向该本机作业传递一些需要完成的批次。
一个本机作业在其他作业之前完成自己负责的批次时,它会从其他本机作业窃取剩余批次。它一次只能窃取本机作业剩余批次的一半,以确保缓存局部性。
要优化该过程,必须指定批次计数。批次计数可以控制您获得的作业数量,以及线程之间重新分配工作的细化程度。批次计数较低(例如 1)可以使线程之间的工作分布更均匀。这样确实会带来一些开销,所以有时候增加批次计数会更好。一种有效的策略是从 1 开始并增加批次计数直到性能增益可忽略不计。
作业代码:
// 将两个浮点值相加的作业
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;
// 调度作业,为结果数组中的每个索引执行一个 Execute 方法,且每个处理批次只处理一项
JobHandle handle = jobData.Schedule(result.Length, 1);
// 等待作业完成
handle.Complete();
// 释放数组分配的内存
a.Dispose();
b.Dispose();
result.Dispose();
2018–06–15 页面已发布
在 2018.1 版中公开了 C# 作业系统 NewIn20181
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.