2016-03-08 106 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()'的目的,並且如果文件大於物理內存,將導致段錯誤。 –

相關問題