Job的依赖项
前言
因为Job多数都是多线程处理,所以处理好线程之间的依赖关系就很重要。类比于Task之间的依赖处理。
一、Job依赖管理
Job在调度时,即调用类似Schedule的函数时,需要传入另外一个Job调度返回的JobHandle。这样当前的Job就会去依赖传入的Job调度完毕后,再去执行。
1.SystemState的依赖
在SystemState中会有一个Dependency属性,代表进入到这个System函数时,它依赖的Job的集合。
2.System中的默认依赖
在使用Entities.ForEach or Job.WithCode时,会按照代码顺序依次依赖,这样就可以偷懒不传递依赖。如下所示,从上到下依次依赖。
protected override void OnUpdate()
{
Entities
.WithName("ForEach_Job_One")
.ForEach((ref AComponent c) =>
{
/*...*/
})
.ScheduleParallel();
Entities
.WithName("ForEach_Job_Two")
.ForEach((ref AnotherComponent c) =>
{
/*...*/
})
.ScheduleParallel();
NativeArray<int> result = new NativeArray<int>(1, Allocator.TempJob);
Job
.WithName("Job_Three")
.WithDisposeOnCompletion(result)
.WithCode(() =>
{
/*...*/
result[0] = 1;
})
.Schedule();
}
也可以手动传入依赖,来提升JOB的并行,比如下面的方式,可以让第一个与第二个JOB并行运行,然后第三个Job去依赖前两个JOB。
protected override void OnUpdate()
{
JobHandle One = Entities
.WithName("ForEach_Job_One")
.ForEach((ref AComponent c) =>
{
/*...*/
})
.ScheduleParallel(this.Dependency);
JobHandle Two = Entities
.WithName("ForEach_Job_Two")
.ForEach((ref AnotherComponent c) =>
{
/*...*/
})
.ScheduleParallel(this.Dependency);
JobHandle intermediateDependencies =
JobHandle.CombineDependencies(One, Two);
NativeArray<int> result = new NativeArray<int>(1, Allocator.TempJob);
JobHandle finalDependency = Job
.WithName("Job_Three")
.WithDisposeOnCompletion(result)
.WithCode(() =>
{
/*...*/
result[0] = 1;
})
.Schedule(intermediateDependencies);
this.Dependency = finalDependency;
}
3.IJobEnity中的默认依赖
在使用IJobEnity中时调度Job,可以不传依赖,默认就是将xSystem中的依赖传给Job,同时更新System的依赖为新的依赖。
4.IJobChunk中的依赖
IJobChunk需要显示传递依赖,这个比较底层,所以需要自己控制依赖,对于一些非常规的调度,可以使用这个方式。