struct SerialSumJob : IJob
{
[ReadOnly]
public NativeArray<float> data;
public float output;
public void Execute ()
{
var len = data.Length;
output = 0;
for (int i = 0; i < len; i++) {
output += data[i];
}
}
}
and running it with
var job = new SerialSumJob { data = data };
job.Schedule ().Complete();
Debug.LogFormat ("job complete: {0}", job.output);
(data was initialized with Random values)
after job was complete, output was still 0.
it makes sense, as structs get copied, but is there a recommended way to enable it? (i can workaround with a single-element NativeArray)
public struct SumJob : IJob<float> {
[ReadOnly] public NativeArray<float> values;
public float Execute() {return 42f;}
}
...
var result = new SumJob{values = ...}.Schedule().Complete();
Could you post a code example of what you mean? Still trying to get my head around the nativearray use and job use for basics such as creating a job that will increment a value…
Would be nice to know what the threading model is here. Like can we mix what would be normal in a concurrent environment here with jobs.
For example if output was declared outside of IJob, and not touched until the job was complete, that would be completely normal in any low latency concurrent app. If you don’t actually need memory barriers, you don’t create them just for the fun of it.
Or if we can use api’s like Interlocked in jobs.
The threading model would basically answer all questions of that type.
I guess they’re going to share details, documentation, etc… when they officially announce the release of the new tech. So far, even though it’s included in Unity, the official statement is “Coming soon: the C# Job System”.
So the job is an actual struct. So what we do internally, is we take all data on the struct copy it out and give it to the job. So its perfectly fine to write back to the float on the job (Because the changed values are only visible on that thread and then discarded), this has no negative impact on performance or determinism.
Arguably its a bit of a strange thing to do and maybe usually a mistakes. I guess we could argue that a static analysis tool should tell the user that writing to the float is likely not making any sense and at least output a warning.
it can make sense to write to a float, to count the area of occupation of one force in an RTS or the pollution level of the land.
i dont understand how N thread writing to the same value is deterministic… i thought that if thread 1 and 2 do value++ then at the end of one round there is a chance that you get only value++ instead of the expected value=value+2
Does that means a Job is able to calculate area of occupation or pollution level of a grid but ForJob will return an erroneous result?
If that’s the case then value types should be allowed on jobs but not on ForJobs
public struct NativeUnit<T> where T : struct {
private NativeArray<T> internalContainer;
public NativeUnit(Allocator allocator) {
this.internalContainer = new NativeArray<T>(1, allocator);
}
public void Dispose() {
this.internalContainer.Dispose();
}
public T Value {
get {
return this.internalContainer[0];
}
set {
this.internalContainer[0] = value;
}
}
}
This has bitten me a few times. You’d think a person would remember, but people don’t because it’s counter-intuitive. I get the why under the hood, but I wish for a way to not get such a productivity tax for these weird nuances.
Maybe give us something like NativeInt, etc, to help people remember.