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]已经不生效了。

 

  

posted @ 2020-03-08 23:51  斯芬克斯  阅读(3022)  评论(0编辑  收藏  举报