使用STL将大型STL向量写入文件的最快方法

时间:2009-11-07 13:52:37

标签: c++ stl

我有一个大的矢量(10 ^ 9个元素)的字符,我想知道将这样的矢量写入文件的最快方法是什么。到目前为止,我一直在使用下一个代码:

vector<char> vs;
// ... Fill vector with data
ofstream outfile("nanocube.txt", ios::out | ios::binary);
ostream_iterator<char> oi(outfile, '\0');
copy(vs.begin(), vs.end(), oi);

对于此代码,将所有数据写入文件大约需要两分钟。实际问题是:“我可以使用STL加快速度吗?”

7 个答案:

答案 0 :(得分:23)

要写入如此大量的数据(~1GB),您应该直接写入输出流,而不是使用输出迭代器。由于向量中的数据是连续存储的,因此这将起作用并且应该更快。

ofstream outfile("nanocube.txt", ios::out | ios::binary);
outfile.write(&vs[0], vs.size());

答案 1 :(得分:3)

ostream_iterator的构造函数的第二个参数存在轻微的概念错误。它应该是NULL指针,如果你不想要一个分隔符(虽然,幸运的是,这将被隐含地对待),或者第二个参数应该被省略。

但是,这意味着在写完每个字符后,代码需要检查指定分隔符的指针(这可能有点效率低)。

我认为,如果你想使用迭代器,也许你可以试试ostreambuf_iterator

其他选项可能包括使用write()方法(如果它可以处理这么大的输出,或者可能以块的形式输出),也许还包括特定于OS的输出函数。

答案 2 :(得分:2)

由于您的数据在内存中是连续的(正如Charles所说),您可以使用低级I / O.在Unix或Linux上,您可以写入文件描述符。在Windows XP上,使用文件句柄。 (这在XP上有点棘手,但在MSDN中有详细记载。)

XP缓冲有点搞笑。如果将1GB块写入句柄,则会比将写入分成较小的传输大小(在循环中)慢。我发现256KB写入效率最高。一旦你编写了循环,你可以玩这个,看看最快的传输大小。

答案 3 :(得分:1)

好的,我用for循环写了方法实现,在每次迭代时写入256KB块(如Rob建议的)数据,结果是16秒,所以问题解决了。这是我谦虚的实现,所以请随意评论:

 void writeCubeToFile(const vector<char> &vs)
 {
     const unsigned int blocksize = 262144;
     unsigned long blocks = distance(vs.begin(), vs.end()) / blocksize;

     ofstream outfile("nanocube.txt", ios::out | ios::binary);

     for(unsigned long i = 0; i <= blocks; i++)
     {
         unsigned long position = blocksize * i;

         if(blocksize > distance(vs.begin() + position, vs.end())) outfile.write(&*(vs.begin() + position), distance(vs.begin() + position, vs.end()));
         else outfile.write(&*(vs.begin() + position), blocksize);
     }

     outfile.write("\0", 1);

     outfile.close();
}

Thnx给大家。

答案 4 :(得分:1)

如果您有其他结构,此方法仍然有效。

例如:

typedef std::pair<int,int> STL_Edge;
vector<STL_Edge> v;

void write_file(const char * path){
   ofstream outfile(path, ios::out | ios::binary);
   outfile.write((const char *)&v.front(), v.size()*sizeof(STL_Edge));
}

void read_file(const char * path,int reserveSpaceForEntries){
   ifstream infile(path, ios::in | ios::binary);
   v.resize(reserveSpaceForEntries);
   infile.read((char *)&v.front(), v.size()*sizeof(STL_Edge));
}

答案 5 :(得分:1)

您可以尝试创建内存映射文件,然后使用memcpy将向量复制到内存映射文件,而不是通过文件i / o方法进行写入。

答案 6 :(得分:-1)

在它上面使用write方法,它毕竟是ram并且你有很多内存..最快,同时寻找灵活性?丢失内置缓冲,提示顺序i / o,丢失迭代器/实用程序的隐藏内容,尽可能避免使用streambuf但是使用boost :: asio来弄脏...