Bil*_* N. 44 c c++ file-io mmap
我有一个Linux应用程序,并行读取150-200个文件(4-10GB).每个文件依次以小的,可变大小的块读取,每个块通常小于2K.
我目前需要从文件集中保持超过200 MB/s的读取速率.磁盘处理这个很好.预计需要超过1 GB/s(目前不在磁盘范围内).
我们已经实现了两个不同的读取系统,它们都大量使用posix_advise:首先是mmaped读取,其中我们映射整个数据集并按需读取.第二个是基于read()/ seek()的系统.
两者都运行良好但仅适用于中等情况,该read()方法更好地管理我们的整体文件缓存并且可以很好地处理100 GB的文件,但是速率受限,mmap能够预先缓存数据使得持续数据速率超过200MB/s易于维护,但无法处理较大的总数据集大小.
所以我的问题来自于:
答:可以在Linux read()上posix_advise调用之外进一步优化类型文件i/o ,或者调整磁盘调度程序,VMM和posix_advise调用是否符合我们的预期?
B:有没有系统的方法让mmap更好地处理非常大的映射数据?
Mmap-vs-reading-blocks 与我正在工作的问题类似,并且提供了一个关于这个问题的良好起点,以及mmap-vs-read中的讨论.
Mat*_*ner 14
回读一下?这些数据的最终目的地是什么?
因为它听起来像你完全是IO绑定,mmap并且read应该没有区别.有趣的部分是如何将数据传输到接收器.
假设您将此数据放入管道,我建议您将每个文件的内容全部转储到管道中.要使用零拷贝执行此操作,请尝试splice系统调用.您也可以尝试手动复制文件,或者cat使用当前文件作为stdin并且将管道作为stdout强制缓冲的实例或其他工具.
if (pid = fork()) {
waitpid(pid, ...);
} else {
dup2(dest, 1);
dup2(source, 0);
execlp("cat", "cat");
}
Run Code Online (Sandbox Code Playgroud)
如果您的处理与文件无关,并且不需要随机访问,则需要使用上面列出的选项创建管道.您的处理步骤应接受来自stdin或管道的数据.
要回答您更具体的问题:
答:可以读取()类型文件i/o除了在Linux上的posix_advise调用之外进一步优化,或者调整了磁盘调度程序,VMM和posix_advise调用是否达到了我们的预期效果?
就告诉内核从用户空间做什么而言,这是一样好的.剩下的由您自己决定:缓冲,线程等等,但它是危险的,可能是非生产性的猜测工作.我只是把文件拼接成一个管道.
B:有没有系统的方法让mmap更好地处理非常大的映射数据?
是.在下面的选项可能会给你真棒性能优势(而且可能使MMAP值得使用比读,以测试):
MAP_HUGETLB
使用"大页面"分配映射.
这将减少内核中的分页开销,如果您要映射千兆字节大小的文件,这将是很好的.
MAP_NORESERVE
不要为此映射保留交换空间.保留交换空间时,可以保证可以修改映射.如果没有保留交换空间,如果没有可用的物理内存,则可能在写入时获得SIGSEGV.
如果实际上没有足够的物理内存+交换来完成整个映射,这将防止内存不足,同时保持实现简单.**
MAP_POPULATE
填充(prefault)页表以进行映射.对于文件映射,这会导致对文件进行预读.以后访问映射不会被页面错误阻止.
这可能会为您提供足够的硬件资源,并且如果预订是有序的,则是懒惰的.我怀疑这个标志是多余的,VFS默认情况下可能做得更好.