Search Unity

DOTS compatible KNN

Discussion in 'Entity Component System' started by pvloon, Jun 11, 2019.

  1. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    591
    Hi All,

    Bit new to DOTS for a project I needed a fast KNN library. I ended up doing one with DOTS!

    https://github.com/ArthurBrussee/KNN

    Was fun to experiment with. Some feedback I came across while developing this:

    - Burst is still super crash prone :/
    - Not being able to allocate containers in bursts jobs is really a bummer
    - When scheduling non overlapping slices of the same array Unity still errors. Would be great if the safety system could account for that.
    - I really want an easier way to do ref returns. There is a way to do it now with UnsafeUtilityEx, but it's a hassle.
    - Burst compiled Delegates can't come soon enough!
    - I wish there was a way to have a job like IJobParralelForBatch, where the pre-amble can be any kind of code, and only the tight loop after is Burst-ified. Right now if you need some kind of more complex setup per batch you essentially have to resort to manually spawning a nr. of jobs.

    But other than that it was good fun to see performance jump up a factor 10 when using DOTS
     
    psuong, starikcetin and hippocoder like this.
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    You can allocate native containers in bursted job without problem with Allocator.Temp. (Exclude NativeQueue)
     
  3. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    A couple thoughts... Something like KNN seems quite low level. Creating a container on the same level that NativeList / NativeArray is a container would make sense. Essentially you assume all risk for safety & leaks but you use atomicsafetyhandle etc to enforce that all usage of your API is completely safe. This also means you can allocate / deallocate as much data as you like with any allocator label on a bursted job.

    When doing that setup it's obviously super important to write unit tests & stress tests to ensure that your implementation is correct and pevents incorrect usage. If you like at Unit tests for BlockStream you will see half of the tests are tests against incorrect usage patterns throwing the expected exceptions.

    I would say that should probably be built as a container written with unsafe code. Also IJobParallelForDeferred is likely what you want. Check out the Physics BlockStream struct for an example of a specialized container.
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
  5. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Yeah we have some really bad stuff with exception handling in there now. It should all be resolved in 19.3.
     
  6. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Also if the speedup you are getting is 10x there is likely something going very wrong. For this kind of code. Combo of datalayout / burst / jobs. Should get somewhere on the order of > 100x speedups.
     
    hippocoder likes this.
  7. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    591
    Thanks Joachim! Great point on equating this to a NativeXXX<> container, that makes a lot of sense. I've integrated some of Unity's safety system now. No idea if I'm missing part of it though.

    10x speedup is just no Burst -> Burst (just check again, and it actually is ~18x). Vs the original pure non-jobified C# code it's definitely even more but haven't measuremed enough along the way. The main demo is mostly waiting on the tree to rebuild, which does jump all over the place in memory and is only single threaded... I'll see if I multithread that someday.

    @eizenhorn: Woops I see why I remember this now. Allocating is fine but calling Dispose() is what breaks Burst - I see now you just shouldn't Dispose Temp memory, makes sense!

    Removing that allows for a much cleaner API and I now run multiple queries as an IJobParralelForBatch, perfect!

    Thanks for the help!
     
  8. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    591
    Last edited: Jun 12, 2019
  9. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    966
  10. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    591
    This was at 00:30 at night so I didn't exactly do due dilligence in measurements here, but from what I remember the change to a ref variable was really minimal if noticable at all. I think LLVM probably does a pretty good job already at not doing that copy - but then - never trust a compiler.

    (So to answer your question: No, it's not worth it 99% of the time, but then this is meant as a low-level lib & the KdNode struct is somewhat larger than ideal)
     
  11. rlabrecque

    rlabrecque

    Joined:
    Aug 27, 2014
    Posts:
    15
    I'd really love to see more of this officially from Unity, what I'm realizing more and more is that game engines should provide building blocks. One problem we ran into recently on our Unreal game was wanting to swap out our Voxel based navigation system for something sparser ala Octree and KD-Tree. I really wish all of these were available with a similar interface so we could have swapped between them easily.
     
  12. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Check out the BVH tree in Unity.Physics it is incredibly well optimized.
     
    siggigg and rlabrecque like this.
  13. rlabrecque

    rlabrecque

    Joined:
    Aug 27, 2014
    Posts:
    15
    Awesome, will do! Thanks Joe!