我可以在MPI中使用API​​读取远程文件吗?

时间:2016-03-08 13:29:17

标签: c mpi

N台机器中的每台机器都有一个独有的数据部分作为二进制文件。 (这些文件只是固定大小数据类型的数组)

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

似乎MPI_File_*操作需要将所有数据文件复制到每台机器的本地文件系统中以具有此功能,除非我有分布式并行文件系统。

1 个答案:

答案 0 :(得分:1)

这可以通过单侧MPI通信来模拟这种情况。从这里开始,我将做出一些假设(其中一些已在您的问题中确认过):

  1. 您的文件是二进制文件,位于非共享文件系统上(在我的示例中,每个进程或等级r将访问名为“/ tmp / input r”的文件<) LI>
  2. 你在Linux / Unix集群上(我将在这里使用一些POSIX函数,我怀疑它可以在Windows机器上运行)
  3. 你的文件太大了,不能被每个进程读入缓冲区并随后暴露(尽管如果文件很小,这可能是最简单的解决方案)
  4. 因此,我们的想法是每个进程在读取模式下打开自己的私有文件,内存映射它,然后将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
    

    正如您所看到的,它既有效又无需提前读取私有文件,也不需要将文件放在共享文件系统上。