gpt4 book ai didi

c++ - 加速文件 I/O : mmap() vs. read()

转载 作者:IT老高 更新时间:2023-10-28 14:00:31 28 4
gpt4 key购买 nike

我有一个并行读取 150-200 个文件 (4-10GB) 的 Linux 应用程序。每个文件依次以小块、可变大小的 block 读取,每个 block 通常小于 2K。

我目前需要从一组文件中保持超过 200 MB/s 的读取速率。磁盘处理得很好。预计需要超过 1 GB/s(目前超出磁盘的范围)。

我们已经实现了两种不同的读取系统,它们都大量使用 posix_advise:首先是一个 mmaped 读取,我们在其中映射整个数据集并继续读取要求。第二个是基于 read()/seek() 的系统。

两者都运行良好,但仅适用于中等情况,read() 方法可以更好地管理我们的整体文件缓存,并且可以很好地处理 100 GB 的文件,但严重受限于速率,mmap 能够预缓存数据,使得 200MB/s 以上的持续数据速率易于维护,但无法处理大的总数据集大小。

所以我的问题来了:

A: read() 类型文件 i/o 是否可以在 Linux 上的 posix_advise 调用之外进一步优化,或者调整磁盘调度程序、VMM 和 posix_advise 调用是和我们预期的一样好?

B:mmap 是否有系统的方法来更好地处理非常大的映射数据?

Mmap-vs-reading-blocks是一个与我正在工作的问题类似的问题,并为这个问题提供了一个很好的起点,以及 mmap-vs-read 中的讨论。 .

最佳答案

读回什么?这些数据的最终目的地是什么?

因为听起来你完全是 IO 绑定(bind)的,所以 mmapread 应该没有区别。有趣的部分在于如何将数据发送到接收器。

假设您将此数据放入管道,我建议您将每个文件的内容全部转储到管道中。要使用零拷贝执行此操作,请尝试 splice系统调用。您也可以尝试手动复制文件,或者派生 cat 的实例或其他可以大量缓冲的工具,当前文件作为标准输入,管道作为标准输出。

if (pid = fork()) {
waitpid(pid, ...);
} else {
dup2(dest, 1);
dup2(source, 0);
execlp("cat", "cat");
}

更新0

如果您的处理与文件无关,并且不需要随机访问,则您希望使用上述选项创建管道。您的处理步骤应该接受来自标准输入或管道的数据。

回答您更具体的问题:

A: Can read() type file i/o be further optimized beyond the posix_advise calls on Linux, or having tuned the disk scheduler, VMM and posix_advise calls is that as good as we can expect?

在告诉内核从用户空间做什么方面,这是最好的。其余的由你决定:缓冲、线程等,但这是危险的,可能是非生产性的猜测工作。我只是将文件拼接到管道中。

B: Are there systematic ways for mmap to better deal with very large mapped data?

是的。 following options可能会给您带来令人敬畏的性能优势(并且可能使 mmap 值得反复阅读和测试):

  • MAP_HUGETLB使用“大页面”分配映射。

    这将减少内核中的分页开销,如果您要映射千兆字节大小的文件,这将非常有用。

  • MAP_NORESERVE不要为此映射保留交换空间。保留交换空间时,可以保证可以修改映射。如果没有保留交换空间,如果没有可用的物理内存,可能会在写入时获得 SIGSEGV。

    如果您实际上没有足够的物理内存 + 用于整个映射的交换,这将防止您耗尽内存,同时保持您的实现简单。**

  • MAP_POPULATE为映射填充(预设)页表。对于文件映射,这会导致文件预读。以后对映射的访问不会被页面错误阻塞。

    如果有足够的硬件资源,并且预取是有序的和惰性的,这可能会为您提供加速。我怀疑这个标志是多余的,默认情况下 VFS 可能会做得更好。

关于c++ - 加速文件 I/O : mmap() vs. read(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8056984/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com