Search Unity

Allocating array in-job. C# array vs. NativeArray?

Discussion in 'Entity Component System' started by 5argon, Aug 5, 2018.

  1. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    We are not using the shared memory area to send data from main thread to the job, so that advantage of NativeArray is gone. Between using NativeArray with Allocation.Temp and then having to .Dispose and just use C# array which one is recommended? Will the C# ones be faster to allocate on thread since it does not have all the "features" of NativeArray?

    Also I am going to sort the data, NativeArray can .Sort but C# also can System.Array.Sort. So this point is a draw?

    I get the appeal of allocating a NativeHashMap in the job since C# Dictionary is a class and does not work. But C# normal array seems to be a subset feature-wise of NativeArray and thus it is a more "lightweight" ones.

    Or did I miss something that could make NativeArray better than C# ones? For instance will Burst able to make in-job allocated NativeArray perform better than C# array? (But IIRC Burst does not compile the job with allocation right now) or garbage collection?
     
    Last edited: Aug 5, 2018
    neonblitzer likes this.
  2. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
  3. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Right, but this one is not a struct member to be copied from main thread but declared right inside the `Execute` method for some array works. I am wondering if making a NativeArray is too much in that case or is it the correct choice instead of just C# array.
     
  4. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    In my opinion, C# array vs. NativeArray is totally depend on your needs and length of array.

    C# array : Generate garbage, but fast access from C# code
    NativeArray : No garbage and fast allocation, but accessing each element from C# needs small overhead (but minimal in IL2CPP world. see https://jacksondunstan.com/articles/4713)

    If your job is executed every frame, allocating C# array in every frame is not good choice :)
     
    eterlan and 5argon like this.
  5. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Allocating a C# array in a job will be a managed allocation. Making managed allocations in job very often has a large performance impact, frequently making the multi-threaded code slower than single threaded code because of lock contention when allocating.
    Managed allocations also does not work with burst, which is another huge performance loss.

    Having said that, NativeArray currently also makes a managed allocation for the DisposeSentinel which makes it incompatible with burst. That allocation will go away in 2018.3 if you are using Allocator.Temp, so once 18.3 is out using NativeArray with Allocator.Temp and burst will be by far the most performant way to allocating a temporary array in a job.
     
  6. georgeq

    georgeq

    Joined:
    Mar 5, 2014
    Posts:
    662
    I'm using Unity 18.3.0b2, and trying to allocate some NativeArrays the way you describe here, but I'm getting this error:

    C:\buildslave\unity\build\Runtime\Export\NativeArray\DisposeSentinel.cs(49,9): error: Using managed `null` is not supported by burst

    While processing function `System.Void Unity.Collections.LowLevel.Unsafe.DisposeSentinel::Create(Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle&,Unity.Collections.LowLevel.Unsafe.DisposeSentinel&,System.Int32,Unity.Collections.Allocator)`

    While compiling job: System.Void Unity.Jobs.IJobParallelForExtensions/ParallelForJobStruct`1<Casablanca.AvoidCollisionJob>::Execute(T&,System.IntPtr,System.IntPtr,Unity.Jobs.LowLevel.Unsafe.JobRanges&,System.Int32)

    Compiler exception: System.NotSupportedException: Using managed `null` is not supported by burst
    at Burst.Compiler.IL.ILVisitor.NotSupported (Burst.Compiler.IL.Syntax.ILInstruction inst) [0x0016b] in <1ba7ce5f379b46f08028b383607c2c83>:0
    at Burst.Compiler.IL.ILVisitor.CompileInternal (Burst.Compiler.IL.Syntax.ILInstruction inst) [0x00523] in <1ba7ce5f379b46f08028b383607c2c83>:0
    at Burst.Compiler.IL.ILVerifier.CompileInternal (Burst.Compiler.IL.Syntax.ILInstruction inst) [0x00000] in <1ba7ce5f379b46f08028b383607c2c83>:0
     
  7. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Nice necro, I almost forgot about this. Probably we will have to wait until full 2018.3 release for null-less implementation of the allocation?
     
  8. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    302
    I'm also interested in this. I've tried a few work-arounds to avoid needing to allocate a native array in a job but it's not really working out so well.

    I'm using the 2018.3 beta already and upgraded mostly to get this functionality (risky I know) and find out it's not there yet.

    @timjohansson do you have any idea which 2018.3 beta will allow native array allocation in a burst job? Will it be on the release notes?

    Thanks
     
  9. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    We are looking into it but we do not know which version the fix will be in yet. It should be in the release notes, but the fix will likely require changes to both Unity and burst so you might have to check both. I'll try to remember to post here when it has landed everywhere.
     
    FROS7 likes this.
  10. jdoxbotica

    jdoxbotica

    Joined:
    Aug 6, 2018
    Posts:
    7
    I already noticed 2018.3b released yesterday had this in the release notes:

    Sounds promising?
     
    Razmot likes this.
  11. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Is allocating/using NativeArray<int> inside Execute() more performant than stackalloc int[]?

    It's also possible to have fixed-size arrays as fields inside structs:
    Code (CSharp):
    1. unsafe struct Job : IJob
    2. {
    3.     private fixed int temp[100];
    4.  
    5.     public void Execute()
    6.     {
    7.     }
    8. }
    I mean, if we don't talk about safety and talk about performance only.
     
    Last edited: Oct 1, 2018
  12. Deleted User

    Deleted User

    Guest

    One month old is not necro :)
     
    KyryloKuzyk and Razmot like this.
  13. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    You can reuse arrays via System.Buffers.ArrayPool<T>.Shared, thus reducing garbage generation and memory pressure: https://www.nuget.org/packages/System.Buffers
     
    Deleted User and johnfrog like this.