4

可能重复:
用 C++ 快速编写二进制文件

我在内存中有大量无符号 32 位整数(15 亿个条目)。我需要将它们写入文件并将它们读回主内存。

现在,我使用:

ofstream ofs;
ofs.open(filename);
for (uint64_t i = 0 ; i < 1470000000 ; i++)
ofs << integers << " " ;

ifstream ifs;
ifs.open(filename);
for (uint64_t i = 0 ; i < 1470000000 ; i++)
ifs >> integers ;

这需要几分钟来执行。任何人都可以帮助我,是否有任何图书馆方法可以更快地做到这一点?或任何建议,以便我可以进行性能测试?任何人都可以向我展示一些mmap用于执行上述操作的简单 C++ 代码(在 Linux 上)吗?

编辑:示例案例

#include<iostream>
#include <stdint.h>
#include <cstdio>
#include <cstdlib>
#include <sstream>

using namespace std;

main()
{
      uint32_t* ele = new uint32_t [100] ;
      for(int i = 0; i < 100 ; i++ )
      ele[i] = i ;

      for(int i = 0; i < 100 ; i++ ){
          if(ele[i] < 20)
          continue ;
          else
          // write  ele[i] to file
          ;   
      }

 for(int i = 0; i < 100 ; i++ ){
          if(ele[i] < 20)
          continue ;
          else
          // read  number from file
          // ele[i] = number * 10 ;
          ;   
      }

     std::cin.get();
}
4

4 回答 4

3

首先要做的是确定时间的去向。格式化和解析文本并非易事,可能需要一些时间,但考虑到文件的大小,实际的写入和读取也是如此。第二件事是确定数据必须有多“可移植”:最快的解决方案几乎可以肯定是 mmap(或其 Windows 等效项)将数组直接写入文件,而不是读取或写入。然而,这并没有提供可移植的表示,甚至升级编译器也可能使数据不可读。(对于今天的 32 位整数不太可能,但它在过去发生过)。

一般来说,如果时间是要阅读和写作,你会想用mmap. 如果要进行格式化和解析,您将需要研究某种二进制格式——如果它使生成的文件更小,这也有助于读写。最简单的二进制格式,使用普通网络标准写入值,只需要:

void
writeInt( std::ostream& dest, int32_t integer )
{
    dest.put( (integer >> 24) & 0xFF );
    dest.put( (integer >> 16) & 0xFF );
    dest.put( (integer >>  8) & 0xFF );
    dest.put( (integer      ) & 0xFF );
}

int32_t
readInt( std::istream& source )
{
    int32_t results = 0;
    results  = source.get() << 24;
    results |= source.get() << 16;
    results |= source.get() <<  8;
    results |= source.get();
    return results;
}

(显然需要添加一些错误检查。)

如果许多整数实际上很小,您可以尝试一些可变长度编码,例如 Google Protocol Buffers 中使用的编码。如果您的大多数整数都在 -64...63 范围内,这可能会导致文件只有四分之一大小(这同样会缩短读写所需的时间)。

于 2013-01-23T09:13:10.863 回答
2

如果您知道大小,只需 fwrite/fread 一个数组。

于 2013-01-23T09:14:44.727 回答
2

通过为输入和输出流使用更大的缓冲区,您可能会获得更好的性能:

ofstream ofs;
char * obuffer = new char[bufferSize];
ofs.rdbuf ()->pubsetbuf (obuffer, bufferSize);
ofs.open (filename);

ifstream ifs;
char * ibuffer = new char[bufferSize];
ifs.rdbuf ()->pubsetbuf (ibuffer, bufferSize);
ifs.open (filename);

解析整数也是ifs >> integers ;相当慢的方法。尝试读取行,然后使用std::strtol()来解析它们。IME,它明显更快。

于 2013-01-23T09:18:59.117 回答
0

如果您只想复制,可以使用它来获得更好的性能:

std::ifstream  input("input");
std::ofstream  output("ouptut");
output << input.rdbuf();

或者设置缓冲区大小可能会提高速度:

char cbuf[buf_size];
ifstream fin;
fin.rdbuf()->pubsetbuf(cbuf,buf_size);

我在回答中没有考虑 long int 问题,因为我根本不知道它们为什么会影响流性能,但我希望它无论如何都会有所帮助。

于 2013-01-23T09:24:12.557 回答