STL:在海量数据中排序和搜索

Posted

技术标签:

【中文标题】STL:在海量数据中排序和搜索【英文标题】:STL: sorting and searching in enormous data 【发布时间】:2017-04-15 20:56:35 【问题描述】:

我有两组点(sourcetarget)。目标是在target 中为每个source 点找到一个唯一的1:1 最近邻 点。

我的尝试按预期工作,但速度慢得离谱。我已经测试了几千点,但在实际场景中点数将是数百万。我不是 STL 方面的专家。有什么建议可以优化吗?

std::vector<UT_Vector3> targetPosVector;
for (auto i = 0; i < targetNumPoints; i++)

    auto pos = target->getPos3(i);

    targetPosVector.push_back(pos);


std::vector<int> uniqueNeighborVector;
for (auto ptoff = 0; ptoff < sourceNumPoints; ptoff++)

    std::vector<std::pair<int, fpreal>> nearpointVector; // neighbor vector in form of "(idx, dist)"

    auto pos = source->getPos3(ptoff);
    for (auto j = 0; j < targetNumPoints; j++)
    
        fpreal dist = pos.distance(targetPosVector[j]);

        std::pair<int, fpreal> neighbor j, dist;
        nearpointVector.push_back(neighbor);
    
    std::sort(nearpointVector.begin(), nearpointVector.end(), [](const std::pair<int, fpreal> &left,
                                                                 const std::pair<int, fpreal> &right)
                                                                 return left.second < right.second; );

    std::vector<int> neighborVector;
    for (auto i : nearpointVector)
    
        neighborVector.push_back(i.first);
    

    // trying to imitate Python's next() function
    // uniqueNeighborList[]
    // uneighbor = next(i for i in neighborVector if i not in uniqueNeighborVector)
    // uniqueNeighborVector = set(uniqueNeighborList.append(uneighbor))
    for (auto i : neighborVector)
         
        if (std::find(uniqueNeighborVector.begin(), uniqueNeighborVector.end(), i) == uniqueNeighborVector.end())
        
            int uneighbor = i; // later on binds to the geometry attribute

            uniqueNeighborVector.push_back(i);

            break;
        
    

在哪里

sourcetargetDetail Geometry数据 distance 是一个计算两个向量之间距离的函数 getPos3 是获取3-float vector 点位置的函数 fpreal又名64-bit float UT_Vector33-float vector sourceNumPointstargetNumPoints 是点数 sourcetarget 几何。

【问题讨论】:

标准库确实没有针对这个任务进行优化。看看专门的库,比如PCL。 这里的问题与其说是 STL,不如说是所选择的算法。您正在生成二次距离对,因此这种方法不会扩展到数百万个点。您将需要使用某种形式的空间细分来快速拒绝不可能的配对,而不是盲目地尝试所有组合。 即便如此,即使是目前的蛮力实现也显得不必要地令人费解。我收集到一个目标点可能只匹配一次,低阶源获得第一个 dib。如果是这样,那么与其生成和排序一个临时向量,然后线性扫描整个目标集,我建议删除使用过的目标(通过交换回)并在没有中间缓冲和排序的情况下在线选择最佳匹配。诚然,它不会让您进入数百万美元,但它可能是一个开始。 目标点随机分布。让我们假设第一个点的最近邻居是 1203,而第二个点可能是 719123 之类的任何东西或具有巨大跳跃的东西。 @Pradeep Barua:太好了,(均匀的)随机分布应该让事情相对容易处理。例如,您可以尝试将目标点划分为 3D 网格结构。然后在搜索过程中直接索引最近的网格条目并逐渐向外扫描,返回并删除找到的第一个点。随着网格大小调整到密度,我相信这应该大致是线性的。 【参考方案1】:

正如 cmets 中提到的,当尝试计算数百万个点时,二次复杂度是失败的。即使您优化了代码,如果方法没有改变,二次复杂度将保持不变。

在我看来,这听起来像是 R3 中的经典 NN 问题。一个众所周知的方法是使用k-d trees,它们允许 O(log n) 查询时间在 O(n log n) 构建时间和线性空间内。可以通过各种库寻求实现:nanoflann、kdtree(这些来自快速搜索,我敢肯定还有包含 k-d 树的复杂库。)

简短回顾:我会使用 3-d 树并在您的目标点集上构建它。然后取每个源点(一个接一个)并在 O(log n) 时间内找到 3-d 树中的最近邻居,每个都将导致 O(|source| log |target|) 时间和 O(|目标|) 大小。

一个相关的question。

【讨论】:

以上是关于STL:在海量数据中排序和搜索的主要内容,如果未能解决你的问题,请参考以下文章

海量数据处理-字典树和倒排索引

海量数据处理 大量数据中找出最大的前10个数 (Top K 问题)

海量数据处理-重新思考排序

Java难点攻克「海量数据计算系列」如何使用BitMap在海量数据中对相应的进行去重查找和排序实战

海量数据查找排序

海量数据处理:经典实例分析