Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Running multiple parallel jobs, which use the same NativeArray, but never overlap indices

Discussion in 'Entity Component System' started by Grizmu, Sep 11, 2019.

  1. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    I'm working on a job scheduler system for big arrays and I'm investigating how to get multiple jobs, using the same NativeArray and taking care of different tasks, to run in parallel.

    Lets assume that:
    -We have a NativeArray of length 1,000,000, which is actually a 1000x1000 array;
    -We have 4 jobs that we want to use on this array;
    -Jobs will not overlap their indices durning execution, that is they'll never read or write to an index of the array that is worked on by a different job.

    DOTS_jobs_1.png

    First method is a straightforward one, just linearly schedule jobs one after another and make them dependent on previously scheduled job. Here execution takes some time, as each job is waiting for previous one to finish:

    DOTS_jobs_2.png

    Second method makes use of a IJobParallelFor and an additional NativeArray, which holds info about which operation should be used for each index. This complicates job structs, as they have to be merged into one, big struct, if they are expected to be run together often:

    DOTS_jobs_3.png

    Hypothetical method that I'm looking to achieve would bypass "You are trying to schedule a new job, which writes to the same NativeArray" error, as job scheduler would take care to never schedule jobs that overlap each other:

    DOTS_jobs_4.png

    I've looked for a way to approach this, but I haven't found yet if it's possible, or if I have to stick with IJobParallelFor, IJobParallelForBatch or create a custom job type.

    Would love to hear your thoughts about it.
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    If you know what you doing and sure in safety, use [NativeDisableContainerSafetyRestrictions](maybe typo in name, I’m on mobile).

    You can use native slices and in this case you reduce complexity.
     
  3. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    as @eizenhorn suggested...what you describe is possible, i use it in example with nativeslice...
    Code (CSharp):
    1.             var vertices = new NativeArray<Vector3>(lengthA * 2 + lengthB * 2, Allocator.TempJob);
    2.             NativeSlice<Vector3> verticesA = new NativeSlice<Vector3>(vertices, 0, lengthA * 2);
    3.             NativeSlice<Vector3> verticesB = new NativeSlice<Vector3>(vertices, lengthA * 2, lengthB * 2);
     
    Grizmu likes this.
  4. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    Thank you, that's exactly what I've been looking for.

    Here is the documentation link for this attribute.

    It would be nice to have a separate attribute just for disabling the scheduling checks for multiple jobs using a single NativeArray, as boundary and dispose checks would still be useful to have.

    NativeSlices are useful if the data is accessed lineraly, or as I've just found out, when they are used to implement a job without using [NativeDisableContainerSafetyRestrictions] for safety checks beforehand.

    In my use case they get too granular when iterating over the NativeArray in the second or third dimension, as each range(row) of the data needs its own NativeSlice and a separate job to process, where the worst case is iterating NativeArray using a single x index and y index iterated from 0 to array.len/width, what would schedule array.len/width jobs each using a NativeSlice of length 1.
     
    forestrf likes this.
  5. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    Yeah sure, then don’t use native slice (it can be a convenience thing) as long as you guarantee not to access the same memory position