Search Unity

[Job System] output scalar value from job

Discussion in 'C# Job System' started by M_R, Jan 11, 2018.

  1. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    I started playing around with the new job system.

    I tried to create a 'sum' job like this:
    Code (CSharp):
    1. struct SerialSumJob : IJob
    2.     {
    3.         [ReadOnly]
    4.         public NativeArray<float> data;
    5.         public float output;
    6.  
    7.         public void Execute ()
    8.         {
    9.             var len = data.Length;
    10.             output = 0;
    11.             for (int i = 0; i < len; i++) {
    12.                 output += data[i];
    13.             }
    14.         }
    15.     }
    and running it with
    Code (CSharp):
    1. var job = new SerialSumJob { data = data };
    2.             job.Schedule ().Complete();
    3.             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)
     
  2. adriant

    adriant

    Unity Technologies

    Joined:
    Nov 1, 2016
    Posts:
    69
    You have to use the single-element NativeArray, there is no other way.
     
    Neiist and MadeFromPolygons like this.
  3. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    ok. slightly feels like a hack though.

    is there something planned for it? like
    Code (CSharp):
    1. public struct SumJob : IJob<float> {
    2.     [ReadOnly] public NativeArray<float> values;
    3.  
    4.     public float Execute() {return 42f;}
    5. }
    6. ...
    7. var result = new SumJob{values = ...}.Schedule().Complete();
     
  4. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,980
    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...
     
  5. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,980
    Nevermind, worked it out :) lightning fast speeds, parallel operations are a great thing!
     
    hippocoder and richardkettlewell like this.
  6. adriant

    adriant

    Unity Technologies

    Joined:
    Nov 1, 2016
    Posts:
    69
    No, nothing is planned. Single-element arrays have been considered to be the best approach for the moment.
     
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    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.
     
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Actually would be nice to have some serious docs and blog time on this subject, it's basically a ground-breaking feature in my view.

    Think for a moment. Threading this easy, without race conditions etc ? wow!
     
    Nexer8 and SNS_Case like this.
  9. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,609
    yep, totally agree.

    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".
     
  10. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,330
    I'm surprised the job system even allowed a public float non native array without a [ReadOnly] in front.
     
  11. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    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.
     
    CodeSmile and Neto_Kokku like this.
  12. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,330
    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
     
  13. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Each thread will receive its own copy of the original struct in the Execute method. So it is deterministic.

    In any case, I think we can agree that writing to value types on the jobs is undesirable and static analysis too should prevent users from doing it.
     
  14. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,330
    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
     
  15. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,980
    I take it back, some examples would be great!
     
  16. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,090
    2020, any new ways to do this? I was very confused that my code didn't work.
     
  17. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,330
    at least emit errors in the console.
     
    tonytopper likes this.
  18. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    982
    I have a wrapper for this:
    Code (CSharp):
    1. public struct NativeUnit<T> where T : struct {
    2.     private NativeArray<T> internalContainer;
    3.  
    4.     public NativeUnit(Allocator allocator) {
    5.         this.internalContainer = new NativeArray<T>(1, allocator);
    6.     }
    7.  
    8.     public void Dispose() {
    9.         this.internalContainer.Dispose();
    10.     }
    11.  
    12.     public T Value {
    13.         get {
    14.             return this.internalContainer[0];
    15.         }
    16.  
    17.         set {
    18.             this.internalContainer[0] = value;
    19.         }
    20.     }
    21. }
     
  19. jonah1nine

    jonah1nine

    Joined:
    Mar 25, 2018
    Posts:
    5
  20. tonytopper

    tonytopper

    Joined:
    Jun 25, 2018
    Posts:
    226
    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.
     
    CodeSmile likes this.
  21. Shinyclef

    Shinyclef

    Joined:
    Nov 20, 2013
    Posts:
    505
    The comment above you from one and half years ago links to NativeReference. For an int reference you'll use NativeReference<int>. You can always extend this yourself if you really really want a type specific container like NativeInt.
     
    Luxxuor and Enzi like this.
  22. tonytopper

    tonytopper

    Joined:
    Jun 25, 2018
    Posts:
    226
    Yeah, for sure. I suppose I could. And hence my allusion to a "productivity tax". The jobs API is powerful but, in my opinion, it is going to take off very slowly unless it is made more intuitive and is better documented
     
  23. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    It is actually very well documented all things considered. The problem you are running into I believe is the fact the documentation has fragmented quite a bit. The components of DOTS that is engine ready and already released vs what is not. Some of this documentation has shifted around, as an example, there are at least 3 places to see what the different Allocations mean, but each one has their own depth of info.

    ANYTHING in Entities or preview related aspects of packages are not meant to "take off" quickly. They are in preview, and are constantly shifting. Writing documentation on foundation built on sand, is a rather expensive time waster on their part. As for not remembering, this is common C# and Unity is working towards matching 1:1 .NET in future releases. One day we shall be free of Mono