在C++中,将大型二进制(1GB-4GB)文件加载到内存中的最快方法是什么

In C++, what is the fastest way to load a large binary (1GB-4GB) file into memory?

本文关键字:内存 加载 是什么 方法 文件 C++ 大型 二进制 1GB-4GB      更新时间:2023-10-16

在Linux 64位(如Amazon EC2实例)上,我需要将几个大的二进制文件加载到内存中。最快的路是什么?

  • ifstream
  • fread
  • POSIX打开
  • POSIX mmap(实际上并没有将整个文件加载到内存中,这会影响性能)
  • 还有别的吗

此外,节点可能会也可能不会第二次启动此可执行文件,因此如果在随后的尝试中更快地加载文件,则会有所帮助。某种预加载步骤甚至可能起作用。

时间将由磁盘I/O决定,因此使用哪种API不如思考磁盘如何工作重要。如果你随机访问一个磁盘(旋转介质),它将花费3到9毫秒来寻找。。。一旦磁盘流式传输,它可以维持大约128MB/秒,这就是比特从磁盘头上脱落的速度。SATA链路或PCIe总线的带宽远高于此(600到2000 MB/秒)。Linux在内存中有一个页面缓存,它将页面的副本保存在磁盘上,因此只要你的机器有足够的RAM,即使你随机访问数据,后续的尝试也会很快。因此,建议是一次读大块。如果你真的想加快初始加载的速度,那么你可以使用mmap来映射整个文件(1GB-4GB),并有一个助手线程来按顺序读取每个页面的第一个字节。

您可以在此处阅读有关磁盘驱动器性能特征的更多信息。

您可以在此处阅读有关页面缓存的更多信息。

鉴于以上信息,我认为mmap是一个很好的候选者。我这么说有几个原因:1.它为您提供完整的文件,而无需实际加载(任何)文件,直到实际需要该部分为止。这对于快速加载来说是一个优势,但如果你最终浏览了每个字节[或接触了文件的每个4KB部分],那么没有太大区别。2.mmap只会将数据从磁盘复制一次到您的页面。在我的测试中,这比在Linux中使用freadread读取更有效(还请注意,对于相当大的读取,freadread之间的差异可以忽略。然而,根据我的经验[我现在已经尝试过各种形式的这种方法好几次了],C++流中的FILE函数几乎没有额外的开销

和往常一样,基准测试总是胜过在互联网上提问。所以你可能会发现,在你的情况下,我上面所说的是不对的。正如所指出的,一旦代码足够好,代码中的任何开销都会与磁盘传输数据的速度相比相形见绌-即使你有一个非常漂亮的RAID系统,有很多并行(SSD?)磁盘等,最终磁盘传输速度也会成为瓶颈。在这一点上,你所能做的就是尽量减少其他开销,并且在磁盘已经传送数据之后尽快将数据获取到应用程序。

"每秒字节数"的一个好的基准是使用dd if=/dev/zero of=somefile bs=4K count=1M(写入文件,然后您可能希望使用dd if=somefile of=/dev/null bs=4K来查看从磁盘读取的效果。

您可以尝试使用带有MAP_POPULATE标志的mmap。我怀疑你能做得更快。