2016-03-08 61 views
1

N台机器中的每台机器都将数据的专有部分作为二进制文件。 (这些文件只是固定大小数据类型的数组)我可以使用MPI中的API读取远程文件吗?

第i个proc是否可以在第j个过程中读取数据文件的特定部分? (例如,第i个PROC从第j个PROC的文件的开头读4096个字节)。

看来MPI_File_*操作要求来复制所有数据文件到每台计算机的本地文件系统具有此功能除非我有分布式并行文件系统。

+0

您定位的是哪种语言和操作系统? – Gilles

回答

1

这可以通过单向MPI通信的方式进行模拟。从这里,我会做出一些假设(其中一些你已经在你的问题确认):

  1. 你的文件是二进制文件,位于非共享文件系统(在我的例子,每个进程或秩r将访问名为“/ tmp目录/输入r”)
  2. 一个文件你是在Linux/Unix集群上(我将在这里使用一些POSIX的功能,我怀疑在Windows机器上会的工作)
  3. 你的文件过大到只能被每个进程读入缓冲区并随后暴露(尽管如果文件很小,这可能是最简单的解决方案)

所以这个想法是,每个进程在读取模式下打开它自己的私有文件,存储器映射它,然后将由mmap()返回的内存地址公开到MPI内存窗口中。一旦完成,每个进程可以使用这个窗口来访问它想要的各种文件的一部分。

这是它会是什么样子:

#include <stdio.h> 
#include <mpi.h> 
#include <sys/mman.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <fcntl.h> 

int main(int argc, char *argv[]) { 

    MPI_Init(&argc, &argv); 

    int rank, size; 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 

    // Open the local file 
    char fname[256]; 
    snprintf(fname, 256, "/tmp/input%d", rank); 
    int fd = open(fname, O_RDONLY); 
    // And memory-map it 
    struct stat st; 
    fstat(fd, &st); 
    size_t len = st.st_size; 
    void *faddr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 

    // Create a MPI memory window with the mapped files 
    MPI_Win win; 
    MPI_Win_create(faddr, len, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win); 

    // Each process reads two integers from the next process' private file 
    int next = (rank + 1) % size; 
    int values[2]; 

    MPI_Win_lock(MPI_LOCK_EXCLUSIVE, next, 0, win); 
    MPI_Get(values, 2, MPI_INT, next, 0, 2, MPI_INT, win); 
    MPI_Win_unlock(next, win); 

    printf("Process %d read values %d and %d from process %d's private file\n", 
      rank, values[0], values[1], next); 

    // Cleaning up 
    MPI_Win_free(&win); 
    munmap(faddr, len); 
    close(fd); 

    MPI_Finalize(); 

    return 0; 
} 

为了测试起见,我创建了一个包含两个整数的一些文件:添加当前进程的等级和其与10000我用这在Linux集群(有几个节点),结果是:

~> mpicc -std=c99 mpimap.c -o mpimap 
~> mpirun -n 10 ./mpimap 
Process 0 read values 1 and 10001 from process 1's private file 
Process 1 read values 2 and 10002 from process 2's private file 
Process 2 read values 3 and 10003 from process 3's private file 
Process 3 read values 4 and 10004 from process 4's private file 
Process 5 read values 6 and 10006 from process 6's private file 
Process 6 read values 7 and 10007 from process 7's private file 
Process 9 read values 0 and 10000 from process 0's private file 
Process 4 read values 5 and 10005 from process 5's private file 
Process 7 read values 8 and 10008 from process 8's private file 
Process 8 read values 9 and 10009 from process 9's private file 

正如你可以看到,它的工作原理和它也不需要读取提前私人文件,也不需要有文件在共享文件sys上TEM。

+0

感谢您的有趣解决方案!现在我有一个问题。我正在使用Infiniband的RDMA功能,它可能会绕过操作系统,甚至CPU直接访问物理内存。我曾经在mmap地区使用MPI API,发现了一些可怕的错误(内核恐慌,http://unix.stackexchange.com/questions/263684/c-app-with-mmap-kills-kernel-kernel-panic-with-mmap )。知道与此相关的任何问题吗? – syko

+0

我之前没有使用这种技术的经验,所以我不能说它是否触发某些内核/内核模块上的错误。我可以告诉你的是,你可以尝试(增强版本)你的集群上的这个小代码,看看你是否可以重现你的内核恐慌。如果是这样,那么你对你的U&L问题有一个微笑...... – Gilles

+1

这可能不会如预期的那样在RDMA网络上工作,例如, IB。驱动程序通常会注册整个缓冲区,这意味着它首先会默认其中的所有页面,然后将其锁定在物理内存中。因此,整个文件将被读入,这会破坏使用'mmap()'的目的,并且如果文件大于物理内存,将导致段错误。 –

相关问题