In all the documentation examples, the job system is reading from source data that never changes, and writes to destination buffers that are never in contention. This isn’t helpful in explaining what is thread-safe and what is not.
Example 1:
In C++ the sum would be an atomic operation, so this is thread-safe provided values never changes, but I’m not sure here.
struct SumArray: IJobParallelFor
{
public NativeArray<float> values;
public float sum = 0;
public void Execute (int index)
{
sum += values[index];
}
}
Example 2:
It isn’t clear what [ReadOnly] does or when the data is blitted
Case 1: The data is blitted under the hood in “job.values = values;” or “job.Schedule”. This would be threadsafe
Case 2: “NativeArray values” is only a pointer. This is not threadsafe, because over multiple frames SumArray2Behaviour.values is changing
struct SumArray2: IJobParallelFor
{
[ReadOnly]
public NativeArray<float> values;
public float sum = 0;
public void Execute (int index)
{
sum += values[index];
}
}
public class SumArray2Behaviour : MonoBehaviour
{
NativeArray<float> values;
void Awake()
{
values = new NativeArray<Vector3>(20, Allocator.Persistent);
}
void Update()
{
for (int i = 0; i < 20; i++)
values[i] = UnityEngine.Random.value;
}
public SumArray2 Schedule()
{
SumArray2 job = new SumArray2();
job.values = values;
job.Schedule();
return job;
}
}
Related to Example 2, what does [ReadOnly] do?
- NativeArray is a pointer to somewhere else. This means that [ReadOnly] means the source data does not change
- NativeArray is an automatically (?) blitted copy of data. This means that [ReadOnly] indicates the thread does not change the blitted copy of data.
Assuming the data is not blitted, do I need to blit the values manually if using [ReadOnly]?
Assume Unity does not blit the data in “job.values = values;” or “job.Schedule”.
By manual blit I mean:: On every usage of job.Schedule() I need to allocate a new NativeArray(), copy the source data to the new NativeArray(), and then schedule the job to work on the new NativeArray(). This ensure the thread is working on a copy of my data
Should the source data in MonoBehaviour be a NativeArray?
Lets say in game code every Update() I want to write an array values, which I know I will pass to the job system.
Option 1. NativeArray instead of Vector3 [ ]
NativeArray samples;
samples = new NativeArray(20, Allocator.Persistent);
Option 2: Use Vector3[ ], but blit to NativeArray every time I process the data
Vector3 [ ] samples;
samples = new Vector3 [20];