Example of proper use for NativeList<>.AsParallelWriter?

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.

        private int GetCenterPointIndex(int polyIndex)
        {
            if (polyIndex > polygons.Length) return -1;

            // Check if we previously created this point
            if (centerPointCache.ContainsKey(polyIndex))
            {
                return centerPointCache[polyIndex];
            }

            // if not, then calculate and create it
            var poly = polygons[polyIndex];
            var p1 = vertices[poly.A];
            var p2 = vertices[poly.B];
            var p3 = vertices[poly.C];


            var x = p1.x + p2.x + p3.x;
            var y = p1.y + p2.y + p3.y;
            var z = p1.z + p2.z + p3.z;

            // todo need to normalize this
            var centerPoint = new float3(x / 3f, y / 3f, z / 3f);
         
            var ret = vertices.Length;
            vertices.Add(centerPoint);
            midPointCache.Add(polyIndex, ret);

            return ret;
        }

In a job you use NativeList.ParallelWriter list;
To queue the job you use list = theList.AsParallelWriter()

A ParallelWriter list can’t resize. The rest works as normal.

My confusion though is if I do “NativeList.ParallelWriter list” then I can’t READ from that. Trying to use list[×] 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 :frowning:

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.

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.

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.

1 Like