从莫顿有序点的平行四叉树构造

时间:2018-02-12 15:02:50

标签: c++ parallel-processing openmp quadtree

我有一组点[(x1,y1),(x2,y2), ..., (xn,yn)],它们是莫顿排序的。我希望从这些点并行构建一个四叉树。我的直觉是在每个核心上构造一个子树并合并所有子树以形成一个完整的四叉树。任何人都可以提供一些高级别的见解或伪代码我可以如何有效地做到这一点?

1 个答案:

答案 0 :(得分:1)

首先考虑一下你的计划:

  • 您确定并行化构建会有所帮助吗?我认为你不会有太大的加速风险。四叉树构造在CPU上相当便宜,因此它将部分受到内存带宽的限制。并行化可能没什么用,除非你有单独的内存总线,例如单独的机器。
  • 如果要在并行机器上并行化构造,通过将点集合分成均匀大小的块来简单地创建单独的四叉树可能是最便宜的。这比其他解决方案有一个很大的优势:当你想要插入更多的点,或者想要查找点时,morton顺序允许你非常有效地确定哪个树包含该点(或者应该包含它,用于插入)。对于窗口查询,你可以进行类似的优化,如果查询窗口的'min / min'和'max / max'角的morton-code位于同一'chunk'(子树)中,那么你只需要查询这一棵树。可以进行更多优化。

如果您真的想在一台机器上创建一个四叉树,有几种方法可以有效地分割数据集:

  • 遍历所有点并确定全局最小值/最大值。然后遍历所有点并将它们(假设4个核心)分配给每个核心,其中每个核心代表一个象限。通过将数据集拆分为4个大小均匀的块,可以很好地并行化这些步骤,从而生成完全适合您的数据集的四叉树。您必须将插入同步到树中,但由于数据集是按照命令进行的,因此锁定冲突应该相对较少。
  • 通过将四边形与Morton坐标对齐,可以完全避免插入过程中的锁定碰撞,使得莫顿曲线(z曲线)仅与象限边界相交一次。缺点:树将是不平衡的,即所有象限不太可能包含相同数量的数据。这意味着您的CPU可能具有相当不同的工作负载,除非您将子树拆分为子子树,依此类推,以更好地分配负载。可以在坐标的morton-code / z-code上识别用于避免z曲线跨越象限边界的分割平面。将z码分成两位的块,每一位用于指示哪个(子)象限选择,即00为低/左,01为低/右,10为上/左,11为上/右。由于你的点是一个命令,你可以简单地使用二进制搜索来找到每个象限的块。我意识到这可能听起来相当神秘而没有更多解释。所以也许你可以看一下PH-Tree,它基本上是Z-Ordered(morton-ordered)四叉树(更像是'trie'而不是'tree')。还有一些深入的解释herehere(无耻的自我广告)。 PH-Tree具有一些不错的属性,例如固有地将深度限制为64级(对于64位数),同时保证小节点(2个维度最多4个条目);与四叉树一样,它也保证任何插入/删除都不会影响多个节点,还可能添加或删除第二个节点。还有一个C ++实现here