Search Unity

Question Example of proper use for NativeList<>.AsParallelWriter?

Discussion in 'Entity Component System' started by jwvanderbeck, Oct 1, 2022.

  1. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    I'm really confused on how to use this properly.

    I have a NativeList that I need to read from as well as APPEND to (I do not need to change anything mid list, just append new things to the end in the job) and I just can't figure it out. If I declare a variable for the list AsParallelWriter then I seem to lose all ability to read from said list.

    Here is the method, it will be called as part of Execute() in a JobParallelFor (hopefully!) The vertices list needs to be both read from and appended to.

    Code (CSharp):
    1.         private int GetCenterPointIndex(int polyIndex)
    2.         {
    3.             if (polyIndex > polygons.Length) return -1;
    4.  
    5.             // Check if we previously created this point
    6.             if (centerPointCache.ContainsKey(polyIndex))
    7.             {
    8.                 return centerPointCache[polyIndex];
    9.             }
    10.  
    11.             // if not, then calculate and create it
    12.             var poly = polygons[polyIndex];
    13.             var p1 = vertices[poly.A];
    14.             var p2 = vertices[poly.B];
    15.             var p3 = vertices[poly.C];
    16.  
    17.  
    18.             var x = p1.x + p2.x + p3.x;
    19.             var y = p1.y + p2.y + p3.y;
    20.             var z = p1.z + p2.z + p3.z;
    21.  
    22.             // todo need to normalize this
    23.             var centerPoint = new float3(x / 3f, y / 3f, z / 3f);
    24.          
    25.             var ret = vertices.Length;
    26.             vertices.Add(centerPoint);
    27.             midPointCache.Add(polyIndex, ret);
    28.  
    29.             return ret;
    30.         }
    31.  
     
  2. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    966
    In a job you use NativeList<T>.ParallelWriter list;
    To queue the job you use list = theList.AsParallelWriter()

    A ParallelWriter list can't resize. The rest works as normal.
     
  3. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    My confusion though is if I do "NativeList<int>.ParallelWriter list" then I can't READ from that. Trying to use list[x] just returns an error.

    I also can't call ANY other methods on that list other than the Add ones. For example, I can't call length on it. Making it a ParallelWriter seems to return a new object that ONLY has the Add methods :(
     
    Last edited: Oct 1, 2022
  4. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    966
    You can't read from a ParallelWriter as it would not be thread safe. For the most part it is but that's what Unity decided on with the implementation.
    So either you add the NativeList as another parameter without the ParallelWriter to read (and disable safety for it with [NativeDisableContainerSafetyRestriction]) or you change your job to a single scheduled one.
     
  5. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    As an alternative, use a separate buffer to read initial data from and do a double buffering technique.
    Swap / perform other operations once the job is done.

    This will allow safe parallel execution at the cost of extra memory.
     
  6. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    Hmm.. ok thanks for the info everyone. Sounds like I really need to step back and put more thought into my algorithms instead of just trying to "jobify" them as they were originally. Might need to rethink how they run and how I manage the data if I'm going to get them running in parallel.
     
    Razmot likes this.