Search Unity

Allocating a NativeArray in a Job Execute() with Allocator.Temp doesn't work with Burst

Discussion in 'Burst' started by ahmidou, Jan 29, 2019.

  1. ahmidou

    ahmidou

    Joined:
    Sep 17, 2012
    Posts:
    87
    Hi this is a follow up from from a 2018.3 beta post(as the forum section has been locked)
    I sen't a bug about it: Case 1110554
    So basically this improvement in 2018.3:
    is just not working and making an error:
    Can someone confirm I didn't got it wrong?
    Thanks!!

    here's the actual job:
    Code (CSharp):
    1.         [BurstCompile]
    2.         private struct OsdKernel2f : IJobParallelFor
    3.         {
    4.             public int m_SRC_STRIDE;
    5.             public int m_DST_STRIDE;
    6.             public KernelUniformArgs args;
    7.    
    8.             [ReadOnly]
    9.             [NativeDisableContainerSafetyRestriction]
    10.             public NativeArray<int> offsets;
    11.             [ReadOnly]
    12.             [NativeDisableContainerSafetyRestriction]
    13.             public NativeArray<int> sizes;
    14.             [ReadOnly]
    15.             [NativeDisableContainerSafetyRestriction]
    16.             public NativeArray<int> indices;
    17.             [ReadOnly]
    18.             [NativeDisableContainerSafetyRestriction]
    19.             public NativeArray<float> weights;
    20.             [ReadOnly]
    21.             [NativeDisableContainerSafetyRestriction]
    22.             public NativeArray<Vector2> inVertices;
    23.             [NativeDisableParallelForRestriction]
    24.             [NativeDisableContainerSafetyRestriction]
    25.             public NativeArray<float> dstBuffer;
    26.    
    27.             NativeArray<float> readVertex(int index)
    28.             {
    29.                 NativeArray<float> v = new NativeArray<float>(2, Allocator.Temp);
    30.                 int vertexIndex = args.srcOffset + index /* m_SRC_STRIDE*/;
    31.                 for (int i = 0; i < args.length; ++i)
    32.                 {
    33.                     v[i] = inVertices[vertexIndex][i];
    34.                 }
    35.                 return v;
    36.             }
    37.    
    38.    
    39.             void WriteVertexSeparate(int index, NativeArray<float> v, int dstOffset, NativeArray<float> dstVertexBuffer)
    40.             {
    41.                 int vertexIndex = dstOffset + index * m_DST_STRIDE;
    42.                 for (int i = 0; i < args.length; ++i)
    43.                 {
    44.                     dstVertexBuffer[vertexIndex + i] = v[i];
    45.                 }
    46.             }
    47.    
    48.             void AddWithWeight(ref NativeArray<float> v, NativeArray<float> src, float weight)
    49.             {
    50.                 for (int i = 0; i < args.length; ++i)
    51.                 {
    52.                     v[i] += weight * src[i];
    53.                 }
    54.             }
    55.    
    56.             public void Execute(int i)
    57.             {
    58.                 int current = i + args.batchStart;
    59.    
    60.                 if (current >= args.batchEnd)
    61.                 {
    62.                     return;
    63.                 }
    64.                 NativeArray<float> dst = new NativeArray<float>(2, Allocator.Temp);
    65.    
    66.                 int offset = offsets[current],
    67.                     size = sizes[current];
    68.    
    69.                 for (int j = 0; j < size; j++)
    70.                 {
    71.                     AddWithWeight(ref dst, readVertex(indices[offset + j]), weights[offset + j]);
    72.                 }
    73.    
    74.                 WriteVertexSeparate(current, dst, args.dstOffset, dstBuffer);
    75.             }
    76.         }
    77.  
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    I think this is only meant to be supported in 2019.1
     
  3. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    Funny thing is upgrading Unity would solve one Burst compilation error and encounter the next when allocating native containers. 2018.3.2 had a divide by zero error. 2018.3.3 had the null reference. 2019.1a did not support the itor operation. 2019.1b might have solved it - if not, we'll be forced to wait for the full release.
     
  4. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    As tertle had said, Temp allocation in jobs only work in 2019.1 and onward. Anything related to Allocators and NativeArray (other NativeContainers are separated) needs an editor update.

    For your case, maybe you can use stackalloc if you are willing to use unsafe code.

    []'s
     
    Seb-1814 likes this.
  5. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    Just tested with 2019.1b, Temp allocation in jobs still doesn't work. Error message now says that the
    ldind.ref instruction is not supported. Looks like the Unity team is adding support for Temp allocation step by step
     
  6. whiskers434

    whiskers434

    Joined:
    Sep 23, 2014
    Posts:
    28
    was this ever fixed and in what version? was it back ported to 2018 LTS?
     
  7. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Nothing will be back ported to 2018.x
    Latest entities requires 2019.3 and won't be back ported either.
     
  8. whiskers434

    whiskers434

    Joined:
    Sep 23, 2014
    Posts:
    28
    cheers, will wait out for 2019 LTS
     
  9. Deleted User

    Deleted User

    Guest

    Use stackalloc with NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray method. Temp allocations are harmful for job performance.
     
  10. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    It's not that bad if you avoid doing them per entity. I consider an allocation per chunk and re-using them (or some other type of grouping) acceptable for most practices.
     
  11. Deleted User

    Deleted User

    Guest

    I tried 1k stackallocs vs 1k Temp allocations over 7 worker threads. The profiler with Temp allocations was full of overhead.
    Slash I am sure stackalloc memory would be faster than Temp.
     
    Last edited by a moderator: Dec 29, 2019
  12. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Yeah 1k allocations is huge.

    I've made a post about this in the past here: https://forum.unity.com/threads/tip-avoid-allocating-per-entity.726275/

    about how I write custom jobs to group allocations which doubled the performance of jobs.