在3D点云,GPU中查找最近的邻居

时间:2018-07-07 09:55:59

标签: c++ multidimensional-array gpu gpgpu nearest-neighbor

我想通过GPU计算点云中每个点的最近邻居。 我的数据集如下:

<number of points in column>
<number of columns>

x   y   z
x   y   z
z   y   z
... ... ... 

将近20 ^ 6分。
我正在使用vector<PointXYZ> Input;来存储数据

class PointXYZ
{
public:
    PointXYZ();
    ~PointXYZ();
    PointXYZ(float X, float Y, float Z) : x(X), y(Y), z(Z) {};

    float x;
    float y;
    float z;

};

读取数据处于for循环中,它将忽略没有信息的点(x == 0 && y == 0 && z == 0)。

PointXYZ* NewPoint = new PointXYZ(x, y, z);
Input.push_back(*NewPoint);

这是我的问题:

  1. 在将数据发送到GPU之前读取数据的最佳输入结构是什么? (当前读数大约需要120秒)。

  2. 我在2d图像中没有正确的点索引(因为我忽略了没有信息的点)。每个点都包含x,y,z值。找到3/6/9最近的邻居的最准确但不是那么先进的算法是什么?通过GPU对该数量的点进行线性比较(强力)效率不高吗?

我当时在看八叉树,但是我不确定在没有适当索引的情况下如何划分点云。

1 个答案:

答案 0 :(得分:0)

我刚刚做了一些测试。我使用了具有10'000'000点的有点聚类的3D数据集。实现是用Java实现的,我使用了qthypercube2实现。

  1. 在测试中,我通常将数据作为大型float [] BLOB存储在数据库中。将1万分保存到内存大约需要0.5秒。
  2. 将数据加载到四叉树中(我使用自己的特殊实现)大约需要4秒钟。
  3. 执行1 000 000次3-NN搜索大约需要20秒,而进行1 000 000次3-N搜索大约需要200秒或3.3分钟。

我从没使用过GPU,但让我们做一些数学运算: 我假设“蛮力”是指将每个点与每个其他点进行比较? 10 ^ 7点表示10 ^ 14比较操作。每个比较花费10个周期(只有一个数字)意味着10 ^ 15个计算周期。假设GPU允许并行执行1000次操作,这仍然意味着10 ^ 12个周期。如果您的GPU的时钟频率为1GHz(每秒10 ^ 9个操作),则总搜索将为10 ^ 12/10 ^ 9 = 10 ^ 3 = 1000秒。 这没有考虑:将数据加载到GPU中,存储(中间)最近的邻居,对中间结果(如果大于1NN)进行排序,...

当然,GPU和NN搜索实现的细节可能会有所不同,数据集的实际大小可能也会有所不同。所有这些可能会减少或增加这1000秒。 同样对于四叉树,数据集特征(聚类等)可能会发挥重要作用,搜索类型也可能会发挥重要作用(我测试了3个最近的邻居)。同样,我的实现是“通用的”,因为它适用于任何维度。专用的3D实施可能会更快。

我的猜测:在1千万点时,使用四叉树应该比GPU版本更快,并且绝对易于实现。