marijnz / NativeQuadtree

A Quadtree Native Collection for Unity DOTS
MIT License
358 stars 30 forks source link

QuadTreeJob iteration, I don't quite get why? #10

Closed MostHated closed 3 years ago

MostHated commented 3 years ago

Hey there, I had a question about the QuadTreeJob seen below:

public void Execute()
{
    for (int i = 0; i < 1000; i++) // <----------------- ?? Does this exist for a reason?
    {
        QuadTree.RangeQuery(Bounds, Results);
        Results.Clear();
    }

    QuadTree.RangeQuery(Bounds, Results);
}

I don't quite understand what is going on here. Why is the query ran 1000 times, cleared, and then ran again? There are no comments pertaining to it, or working examples aside from the one test. I was just finishing up making a new job, but I wanted to know if that was actually necessary for some purpose related to functionality that I am just not seeing, or can I simply omit the iterations?

Thanks, -MH

marijnz commented 3 years ago

Hey, this is meant as an example to run jobs. You'd want to run queries in batches so avoid job overhead.

Feel free to change however you like ;)

MostHated commented 3 years ago

Ok, I figured as much, but just wanted to be sure.

In regards to custom jobs, do you happen to know if there is something within the query that might keep it from being able to run as a parallelfor job? I kept trying but always get an exception. I switched it back to just IJob without changing anything else except for swapping out the index and it worked straight away, so I am not sure what it was mad about.

This works with no issue.

Using IJob ```cs private NativeArray keyList; private NativeMultiHashMap boundsMap; private NativeMultiHashMap> resultsMap; [BurstCompile] public struct RangeQueryMultiJob2 : IJob where T : unmanaged { [ReadOnly] public NativeArray keys; [ReadOnly] public NativeMultiHashMap Bounds; [ReadOnly] public NativeQuadTree QuadTree; public NativeMultiHashMap>.ParallelWriter Results; public void Execute() { for (int i = 0; i < keys.Length; i++) { var bounds = Bounds.GetValuesForKey(keys[i]); foreach (var b in bounds) { var results = new NativeList>(Allocator.Temp); QuadTree.RangeQuery(b, results); for (var j = 0; j < results.Length; j++) { Results.Add(keys[i], results[j]); } results.Dispose(); } } } } // ---------------------------------------- // -- Other stuff omitted for brevity ----- var jobHandle = new RangeQueryMultiJob2 { keys = keyList, QuadTree = quadTree, Bounds = boundsMap, Results = resultWriter }; JobHandle handle = jobHandle.Schedule(); handle.Complete(); ```

But this always comes back with errors.

IJobParallelFor ```cs private NativeArray keyList; private NativeMultiHashMap boundsMap; private NativeMultiHashMap> resultsMap; [BurstCompile] public struct RangeQueryMultiJob : IJobParallelFor where T : unmanaged { [ReadOnly] public NativeArray keys; [ReadOnly] public NativeMultiHashMap Bounds; [ReadOnly] public NativeQuadTree QuadTree; public NativeMultiHashMap>.ParallelWriter Results; public void Execute(int index) { var bounds = Bounds.GetValuesForKey(keys[index]); foreach (var b in bounds) { var results = new NativeList>(Allocator.Temp); QuadTree.RangeQuery(b, results); for (var j = 0; j < results.Length; j++) { Results.Add(keys[index], results[j]); } results.Dispose(); } } } // ---------------------------------------- // -- Other stuff omitted for brevity ----- var jobHandle = new RangeQueryMultiJob2 { keys = keyList, QuadTree = quadTree, Bounds = boundsMap, Results = resultWriter }; JobHandle handle = jobHandle.Schedule(); handle.Complete(); ```

Simply switching from Parallel to IJob made it go away, and I can't seem to spot what or where might be the cause, just that the line that was shown at top of the stacktrace was var jobHandle = new RangeQueryMultiJob2<int> (well, at the time was however you had it, so more like var jobHandle = new QuadTreeJobs.RangeQueryMultiJob2<int>)

The error message was something along the lines of "dependency invalidoperationexception: object is not initialized or has already been destroyed."

If you have any suggestions, I would definitely appreciate hearing them. Thanks, -MH

MostHated commented 3 years ago

Actually, nevermind on the above, I got it working. I came across a newer repo that was using IJobFor instead of IJobParallel, then I just used ScheduleParallel() and now it works perfect. I just needed to mind the API changes.