在我的问题中,域中有N个点,它们以某种方式随机分布。对于每个点,我需要找到距离小于给定双精度浮点数DIST的所有邻居点。
在Thrust中有一种有效的方法吗?
顺序,我会使用邻居表,希望实现大约O(n)而不是O(n ^ 2)的朴素算法。
我找到了2D铲斗排序的推力示例,这非常适合我问题的第一部分。但这还不够,因为对于每个存储桶我需要找到相邻存储桶中的所有点,然后计算它们的距离并查看它们中的任何一个是否小于DIST。查找邻居和计算距离应该相对容易,但是将这些符合条件的点添加到结果数组似乎我很难在Thrust中实现。
一种重新解释这个特殊问题的方法是 - 我有两个2D数组A1和A2,列号表示2D桶的索引,每列具有不同数量的元素,这些元素是我的点的索引。 A1列(i)中的每个元素将与A2的colunm(i)中的每个元素形成一个潜在的对,并且所有符合条件的对应记录到结果数组中。
我可以使用CUDA内核并分配大量可能未使用的内存作为解决方法,但这将是我想要做的最后一件事。
提前致谢。
答案 0 :(得分:2)
完整的解决方案超出了单个Stack Overflow答案的范围,但是讨论了如何使用Thrust在此存储库中构建2D空间索引:
答案 1 :(得分:2)
另一种比创建四叉树更简单的可能性是使用邻域矩阵。
首先将所有点放入2D方形矩阵(如果处理三维,则为3D立方网格)。然后,您可以运行完整或部分空间排序,因此点将在矩阵内排序。
具有小Y的点可以移动到矩阵的顶行,同样,具有大Y的点将移动到底行。具有小X坐标的点也会发生同样的情况,这些点应移动到左侧的列。对称地,具有大X值的点将转到右列。
在进行空间排序后(有许多方法可以通过串行或并行算法实现这一点),您可以通过访问点P实际存储在其中的相邻单元格来查找给定点P的最近点。邻域矩阵。
如果将此矩阵放入纹理内存中,您可以使用CUDA中的所有空间缓存来快速访问所有邻居!
您可以在下面的论文中阅读有关此想法的更多详细信息(您可以在线找到它的PDF副本):基于紧急行为的GPU上的超大规模人群模拟。
排序步骤为您提供有趣的选择。您可以使用本文中描述的奇偶换位排序,这种排序非常简单(即使在CUDA中)。如果你只运行一次,它会给你一个局部排序,如果矩阵接近排序,这可能已经很有用了。也就是说,如果你的点移动缓慢,它将为你节省大量的计算。
如果你需要一个完整的排序,你可以多次运行这种奇偶换位传递(如下面的维基百科页面所述):
http://en.wikipedia.org/wiki/Odd%E2%80%93even_sort
还有来自同一作者的第二篇论文,描述了3D的扩展并使用了三次的bitonic排序(高度平行,但不是空间排序)。他们声称它比单一的偶数换位通道更精确,并且比完整排序更有效。本文是用于GPU上的大规模3D人群模拟的邻域网格数据结构。