I have a collection of points [(x1,y1),(x2,y2), ..., (xn,yn)]
which are Morton sorted. I wish to construct a quadtree from these points in parallel. My intuition is to construct a subtree on each core and merge all subtrees to form a complete quadtree. Can anyone provide some high level insights or pseudocode how may I do this efficiently?
Asked
Active
Viewed 1,119 times
0

ascetic652
- 472
- 1
- 5
- 18
1 Answers
1
First some thought on your plan:
- Are you sure that parallelizing construction will help? I think there is a risk that you won't a much speedup. Quadtree construction is rather cheap on the CPU, so it will be partly bound by your memory bandwidth. Parallelization may not help much, unless you have separate memory buses, for example separate machines.
- If you want to parallelize construction on parallel machines, it may be cheapest to simply create separate quadtrees by splitting your point collection in evenly sized chunks. This has one big advantage over other solution: When you want insert more points, or want to look up points, the morton order allows you to pretty efficiently determine which tree contains the point (or should contain it, for insertion). For window queries you can do a similar optimization, if the morton-codes of the 'min/min' and the 'max/max' corners of the query-window lie in the same 'chunk' (sub-tree), then you only need to query this one tree. More optimizations are possible.
If you really want to create a single quadtree on a single machine, there are several ways to split your dataset efficiently:
- Walk through all points and identify global min/max. Then walk through all points and assign them (assuming 4 cores) to each core, where each core represents a quadrant. These steps are well parallelizable by splitting the dataset into 4 evenly sized chunks, and it results in a quadtree that exactly fits your dataset. You will have to synchronize insertion, into the trees, but since the dataset is morton ordered, there should be relatively few lock collisions.
- You can completely avoid lock collisions during insertion by aligning the quadtrants with Morton coordinates, such that the morton-curve (a z-curve) crosses the quadrant borders only once. Disadvantage: the tree will be imbalanced, i.e. it is unlikely that all quadrants contain the same amount of data. This means your CPUs may have considerably different workloads, unless you split the sub-tree into sub-sub-trees, and so on, to distribute the load better. The split-planes for avoiding the z-curve to cross quadrant borders can be identified on the morton-code/z-code of your coordinates. Split the z-code in chunks of two bits, each to bits tell you which (sub-)quadrant to choose, i.e. 00 is lower/left, 01 is lower/right, 10 is upper/left and 11 is upper/right. Since your points a morton ordered, you can simply use binary search to find the chunks for each quadrant. I realize this maybe sound rather cryptic without more explanation. So maybe you can have a look at the PH-Tree, it is essentially are Z-Ordered (morton-ordered) quadtree (more a 'trie' than a 'tree'). There are also some in-depth explanations here and here (shameless self advertisement). The PH-Tree has some nice properties, such as inherently limiting depth to 64 levels (for 64bit numbers) while guaranteeing small nodes (4 entries max for 2 dimensions); it also guarantees, like the quadtree, that any insert/removal will never affect more than one node, plus possibly adding or removing a second node. There is also a C++ implementation here.

TilmannZ
- 1,784
- 11
- 18
-
Thanks for your answer! I think your first approach makes more sense to me, but my problem is, how to merge those subtrees? @TilmannZ – ascetic652 Feb 14 '18 at 00:32
-
Each subtree is exactly one quadrant, so to merge them you simply create a root node that encompasses (and references) the four subtrees. – TilmannZ Feb 14 '18 at 21:49
-
If I have more than four cores, say 8 corse, how can I do that? can you show me a code to do that? – ascetic652 Feb 15 '18 at 00:42
-
For 8 cores you can assign each core half of a quadrant (or two sub-quadrants). Then takes the halves from two cores pairwise to construct a full quadrant. Then put the four quadrants into your root node. The actual code depends very much on the quadtree implementation, you just need a methods/functions to add quadrants (subtrees) to a parent quadrant. – TilmannZ Feb 15 '18 at 18:31