在C++中,将大型二进制(1GB-4GB)文件加载到内存中的最快方法是什么
In C++, what is the fastest way to load a large binary (1GB-4GB) file into memory?
在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中使用fread
或read
读取更有效(还请注意,对于相当大的读取,fread
和read
之间的差异可以忽略。然而,根据我的经验[我现在已经尝试过各种形式的这种方法好几次了],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
。我怀疑你能做得更快。
- 原子加载和存储与内存顺序放宽
- 如何从内存缓冲区加载张量流图
- 我在 IDA 或 dbg 或 olly 上看到的内存是否与我在 RAM 上实时加载的内存相同?
- 从C/C++(Win64)中的内存加载64位DLL
- 对外部函数的调用是否强制从内存加载
- 将使用 4 或 8 个对齐规则将加载处理到内存中
- C++:类如何将自身加载到内存中以递增全局变量?
- 加载字节数组(从内存)到libpng c
- 将内存保存到文件并加载它而不必解析数据?
- 加载时间,遍历时间,不同数据段C/C 的内存使用率
- 急切地加载整个模型以估计张量流的内存消耗
- 从内存加载动态库
- 为什么编译器在循环中从内存加载此指针
- SFML无法从内存加载图像,未提供任何数据
- 在启动时从内存加载QImages
- 在非托管程序中托管CLR时从内存加载程序集
- CImage::在不使用CreateStreamOnHGlobal的情况下从内存加载()
- 当从内存加载PNG时,Libpng错误无效的块类型
- gdkpixbuf从内存加载图像
- 从内存加载CA证书