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

时间:2013-02-11 22:30:13

标签: c++ linux posix

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

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

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

3 个答案:

答案 0 :(得分:6)

时间将由磁盘I / O占主导地位,因此您使用的API并不像考虑磁盘的工作方式那么重要。如果你随机访问一个磁盘(旋转媒体),它将花费3到9毫秒来寻找......一旦磁盘正在流式传输,它可以维持大约128 MB /秒,这就是从磁头开始的位数。 SATA链路或PCIe总线具有比这更高的带宽(600到2000 MB /秒)。 Linux在内存中有一个页面缓存,它在磁盘上保留一份页面副本,因此如果您的计算机有足够的RAM,后续尝试将很快,即使您随后随机访问数据也是如此。所以建议一次读取大块。如果你真的想加快初始加载,那么你可以使用mmap映射整个文件(1GB-4GB)并有一个帮助程序线程按顺序读取每个页面的第一个字节。

您可以阅读有关disk drive performance characteristics here.

的更多信息

您可以阅读有关page cache here.

的更多信息

答案 1 :(得分:0)

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

与往常一样,基准测试总是胜过互联网。所以你可能会发现我上面所说的不适合你的情况。正如所指出的,一旦代码足够好,代码中的任何开销都会被磁盘提供数据的速度相形见绌 - 即使你有一个非常花哨的RAID系统有很多并行(SSD?)磁盘等,最终磁盘传输速度将是瓶颈所在。此时您所能做的就是尝试尽可能减少其他开销,并在磁盘交付数据后尽快将数据提供给应用程序。

“每秒字节数”的一个很好的基准是使用dd if=/dev/zero of=somefile bs=4K count=1M(写一个文件,然后你可能希望dd if=somefile of=/dev/null bs=4K看看你能从磁盘读取的程度。

答案 2 :(得分:0)

您可以使用mmap标记尝试MAP_POPULATE。我怀疑你能不能更快地做到这一点。