NativeArray数据并行写入
按照一般的写法,write会产生race condition,所以需要通过依赖关系按顺序执行:
using UnityEngine; using Unity.Jobs; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; public struct WritePartOfArrayJob : IJobParallelFor { [ReadOnly] public NativeArray<float> source; [NativeDisableContainerSafetyRestriction] public NativeArray<float> dest; public int startIndex; public void Execute(int index) { int idx = startIndex + index; dest[idx] = source[index]; } } public class Job_CombineWriting : MonoBehaviour { private void Start() { NativeArray<float> array1 = new NativeArray<float>(5, Allocator.TempJob); NativeArray<float> array2 = new NativeArray<float>(5, Allocator.TempJob); for (int i = 0; i < 5; ++i) { array1[i] = i; array2[i] = i + 5; } NativeArray<float> arrayCombine = new NativeArray<float>(10, Allocator.TempJob); WritePartOfArrayJob job1 = new WritePartOfArrayJob() { source = array1, dest = arrayCombine, startIndex = 0, }; JobHandle handle1 = job1.Schedule(array1.Length, 1); WritePartOfArrayJob job2 = new WritePartOfArrayJob() { source = array2, dest = arrayCombine, startIndex = 5, }; JobHandle handle2 = job2.Schedule(array2.Length, 1, handle1); handle2.Complete(); for(int i = 0; i < arrayCombine.Length; ++i) { Debug.Log(arrayCombine[i]); } array1.Dispose(); array2.Dispose(); arrayCombine.Dispose(); } }
job2,在schedule的时候会依赖job1,这样就不会产生冲突。
但是也可以通过如下方法并行执行,分别写入目标array的不同索引范围:
NativeArray<float> arrayCombine = new NativeArray<float>(10, Allocator.TempJob); NativeArray<JobHandle> handles = new NativeArray<JobHandle>(2, Allocator.TempJob); WritePartOfArrayJob job1 = new WritePartOfArrayJob() { source = array1, dest = arrayCombine, startIndex = 0, }; handles[0] = job1.Schedule(array1.Length, 1); WritePartOfArrayJob job2 = new WritePartOfArrayJob() { source = array2, dest = arrayCombine, startIndex = 5, }; handles[1] = job2.Schedule(array2.Length, 1); JobHandle.CompleteAll(handles);
这个用法的关键在于给write的NativeArray设置属性:[NativeDisableContainerSafetyRestriction]。
这个属性可以用来禁用job的 safety system,让你对NativeArray拥有完全的控制权,同时系统也就不会帮你定位race condition等情况,所以在使用的时候,需要自己确保安全性。
ps:旧的用法[NativeDisableParallelForRestriction]已经不生效了。