排序和连接数百万或数十亿STL向量的最快方法

时间:2012-08-14 16:24:30

标签: c++ vector

将数百万或数十亿个STL向量排序并连接成单个STL向量的最佳方法是什么。目前,我这样做的方法是迭代向量并执行每个操作。

这是伪代码

typedef unsigned long long int ULLInt;

ULLInt N = 1000000;

vector<vector<ULLInt> > vecVec( N, vector<ULLInt>() );
vector<ULLInt>          concatVec;

// ...
// ... fill vectors inside vecVec here 
// ..  we also get here the total number of values inserted in all vectors (count)
// ...

// reserve the space
concatVec.reserve( count);

// sort each vector and concatenate them in sequence
for( ULLInt i=0; i<N; i++)
  sort( vecVec[i].begin(), vecVec[i].end() );
  concatVec.insert( concatVec.end(), vecVec[i].begin(), vecVec[i].end() );
end for

请注意,不需要对concatVec进行排序。谢谢你的建议。

4 个答案:

答案 0 :(得分:3)

我要做的一件事就是问你是否真的需要连接一百万个std :: vectors。如果您将每个向量添加到列表并创建自己的迭代器来遍历每个向量中的每个元素,该怎么办?对于大多数算法而言,这与一个大型向量无法区分。并且,根据负载,在自定义迭代器中完成的额外工作将远远少于实际连接所有向量所需的所有工作。

答案 1 :(得分:1)

这个怎么样:

  • 将矢量拆分为核心堆。计算每堆所需的尺寸
  • 为所有数据保留向量中的空间
  • 将此向量拆分为核心部分。
  • 将零件和桩送入螺纹进行合并。

一些快速代码(概率不会编译,但你可能会得到重点):

typedef vector<vector<ULLINT>> ManyVectors; 

void merge(ManyVectors vector_of_vectors) {
  const int cores = 16;
  std::array<ManyVectors, cores> piles = split_vector(vector_of_vectors,cores);
  std::array<size_t, cores> sizes = calculate_sizes(piles,cores);
  std::vector<ULLINT> result;
  result.reserve(sum_of_sizes(sizes));
  int used = 0; 
  int core = 0;
  for (ManyVectors& pile: piles) {
    std::thread(merge_vectors, pile, result.begin()+used);
    used += sizes[core];
    core += 1;  
  }
}

答案 2 :(得分:1)

如果vecVec中的向量按升序填充(我从聊天中了解 - 这是您的用例),那么您可以尝试使用一个向量而不是多个小向量,在单独的索引数组中维护每个向量的开始索引。 这将通过“构建”子矢量来避免昂贵的连接。

#include <vector>
#include <algorithm>
#include <cstdlib>
#include <iterator>

int main(int argc,char *argv[])
{
    using namespace std;
    typedef int Payload;
    vector<Payload> vec;
    vector<size_t> indices;
    for(unsigned i=0;i!=100;++i)
    {
        indices.push_back(vec.size()); // begin index of current vector
        // filling current sub-vector
        generate_n(back_inserter(vec),777+i,rand);
    }
    indices.push_back(vec.size()); // end of last vector, or begin of
                                   // one-past last vector

    // sorting each sub vector
    for(size_t i=0;i+1!=indices.size();++i)
    {
        // can be done in parallel. be aware of possible false sharing
        sort(vec.begin()+indices[i],vec.begin()+indices[i+1]);
    }
    return 0;
}

答案 3 :(得分:0)

每次代码插入其中一个向量的内容时,它必须确保目标向量具有足够的内存来保存结果。这意味着它将经常为目标向量重新分配内存。这意味着复制其内容,代码最终会做很多次。将目标矢量的内存预先分配给最终的完整大小会更快 。阅读vector::reserve()