【问题标题】:How can you mmap in parallel for faster file reading?如何并行映射以加快文件读取速度?
【发布时间】:2015-11-07 04:16:54
【问题描述】:

我正在通过this code 工作,现在mmap 工作,但我想知道我是否可以并行使用mmap,如果可以,如何完成它。假设我在并行文件系统(GPFSRAID0 等)上有我的数据,并且我想使用n 进程读取它。

例如,我如何让每个处理器将1/nth 的连续数据块读入内存?或者,或者,将每个 nth 内存块(1 B、1 MB、100 MB、1 GB,无论我选择什么进行优化)读入内存?

我在这里假设一个posix 文件系统。

【问题讨论】:

  • 使用mmap() 会让你受制于内核的虚拟内存管理器。而且由于创建物理到虚拟的映射需要是线程安全的,它往往会在负载下获得单线程。查看lio_listio() 执行多个异步IO 操作。 man7.org/linux/man-pages/man3/lio_listio.3.html 如果您要流式传输大量数据(读取一次,不要查找),请使用直接 IO www-01.ibm.com/support/knowledgecenter/SSFKCN_3.5.0/…
  • 如果我想在重量级流程范式中实现这一点怎么办?像 mpi 这样的分布式内存环境,其中每个等级获得 1/n 的数据并对其进行处理?会不会出现同样的问题?如果不是,我如何将第 i 个 1/n 的数据映射到内存中?
  • 多个集群物理服务器进行读取?然后每次读取都必须是单线程的。 mmap() 可能有效,但我看到文件系统提供数据的速度非常快,比创建虚拟到物理映射的速度还要快。如果你的磁盘那么快,mmap() 就不能正常工作。如果您没有任何位置并且最终不得不在集群中传递文件数据,这可能比快速文件系统慢很多。这完全取决于您的处理需求 - 要真正快速运行,您必须调整一切以协同工作,并且不能抽象出物理设计。
  • mmap() 可以将任意数量的字节从任意偏移量映射到文件中。 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); length 是要映射的字节数,offset 是要开始映射的文件的偏移量。 linux.die.net/man/2/mmap

标签: c linux multithreading parallel-processing mmap


【解决方案1】:

这是我的mpi 并行阅读功能。它根据pagesize 将文件分割成n 连续片段,并让每个进程通过mmap 读取单独的片段。最后需要完成一些额外的技巧,因为进程i 将(可能)获得一行的前半部分,因为它是最后一行,而进程i+1 将获得与第一行相同的行的后半部分。

ikind nchars_orig; // how many characters were in the original file
int pagesize = getpagesize();
off_t offset;
struct stat file_stat;
int finp = open(inpfile, O_RDONLY);
int status = fstat(finp, &file_stat);
nchars_orig = file_stat.st_size;

// find out hwich pieces of the file each process should read
ikind nchars_per_proc[nprocs];
for(int ii = 0; ii < nprocs; ii++) {
    nchars_per_proc[ii] = 0;
}   
// start at the second to last proc, so the last proc will get hit first
// we will decrement him at the end, so this will distribute the work more evenly
int jproc = nprocs-2;
ikind nchars_tot = 0;
ikind nchardiff = 0;
for(ikind ic = 0; ic < nchars_orig; ic+= pagesize) {
    jproc += 1;
    nchars_tot += pagesize;
    if(jproc == nprocs) jproc = 0;
    if(nchars_tot > nchars_orig) nchardiff = nchars_tot - nchars_orig;
    nchars_per_proc[jproc] += pagesize;
}   
nchars = nchars_per_proc[iproc];
if( iproc == nprocs-1 ) nchars = nchars - nchardiff;
offset = 0;
for(int ii = 0; ii < nprocs; ii++) {
    if( ii < iproc ) offset += nchars_per_proc[ii];
} 
cs = (char*)mmap(0, nchars, PROT_READ, MAP_PRIVATE, finp, offset);

【讨论】:

  • 请重新阅读@Andrew Henie 对原始问题的评论。 mmap() 并不比显式磁盘 IO 快(它使用相同的磁盘/内存总线/通道)。您只能将“在 I/O 上阻塞”换成“被页面错误阻塞”。
  • 这里我更关心的是高效的 io 吞吐量。这些文件在网络附加存储上的大小将是 TB,并且一次发送 mmap 与mpi 并行读取文件)所以现在我可以测试我的理论了。
猜你喜欢
  • 1970-01-01
  • 2011-07-07
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-26
  • 2011-12-30
  • 2018-04-24
相关资源
最近更新 更多