簡體   English   中英

排序和連接百萬或十億個STL向量的最快方法

[英]Fastest way to sort and concatenate million or billion STL vectors

將數百萬個或十億個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進行排序。 感謝您的建議。

我要做的一件事是詢問您是否真的需要容納一百萬個std :: vectors。 如果將每個向量添加到列表中並制作自己的迭代器來遍歷每個向量中的每個元素怎么辦? 對於大多數算法,這與一個龐大的向量是無法區分的。 並且,根據負載,在自定義迭代器中完成的額外工作將遠遠少於實際連接所有向量所需的全部工作。

這個怎么樣:

  • 將向量拆分為核心堆。 計算每堆所需的大小
  • 在向量中為所有數據保留空間
  • 將此向量拆分為核心部分。
  • 將零件和樁送入螺紋進行合並。

一些快速代碼(可能不會編譯,但是您可能會明白這一點):

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;  
  }
}

如果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;
}

每次代碼插入向量之一的內容時,都必須確保目標向量有足夠的內存來保存結果。 這意味着它將頻繁地為目標向量重新分配內存。 這意味着復制其內容,並且代碼最終要執行多次。 這將是更快的目標向量最終全尺寸預分配內存。 了解有關vector::reserve()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM