2011-09-29 61 views
2

我有一個MPI代碼,其中進程讀取二進制文件並將其重新寫回。數據分發的方式是進程0讀取(然後寫入)文件的前半部分,而進程1讀取(然後寫入)文件的後半部分。現在的問題是輸入文件和輸出文件不匹配(差異顯示它們不同)。如果只有一個進程,一切正常。有人能指出哪裏出了問題嗎?在簡單MPI代碼中讀寫測試文件時出錯

使用的openmpi,編譯如下:提前的mpirun -np 2 ./test_mpi

感謝:mpicc -Wall test_mpi.c -o test_mpi
運行方式。

#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 

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

    int rank, np, i; //np = no. of processes 
    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &np); 

    int filesize = 48*1048576; //input filesize 48MB 

    double *data = (double*) malloc (filesize/np); 
    FILE* fpa; 
    fpa = fopen ("512_featurevec.out", "rb"); 
    fseek(fpa, filesize/np*rank, SEEK_SET); 
    printf("read: %d\n", (int)fread(&data[0], sizeof(double), filesize/(np*sizeof(double)), fpa)); 
    fclose(fpa); 

    char* outfile = "outfile.txt"; 
    for(i=0; i<np; i++) { 
     if(rank == i) { 
      fpa = fopen (outfile, "ab"); 
      fseek(fpa, filesize/np*rank, SEEK_SET); 
      fwrite (&data[0], sizeof(double), filesize/(np*sizeof(double)), fpa); 
      fclose (fpa); 
     } 
    } 

    free(data); 
    MPI_Finalize(); 
    exit(0); 
} 
+0

請不要強制轉換由malloc()返回的指針。你根本不需要碰它,如果你這樣做,你可能會允許錯誤。 –

回答

0

回答我的問題,但這個工程:

char* outfile = "outfile.txt"; 
    for(i=0; i<np; i++) { 
     if(rank == i) { 
      fpa = fopen (outfile, "ab"); 
      fseek(fpa, filesize/np*rank, SEEK_SET); 
      fwrite (&data[0], sizeof(double), filesize/(np*sizeof(double)), fpa); 
      fclose (fpa); 
     } 
     MPI_Barrier(comm); 
    } 

出於某種原因,如果proc 1在proc 0之前到達並且找到一個空文件到某個值,它確實將文件指針定位到正確的偏移量(通過ftell驗證),但是隻寫偏移量0(我必須做東西錯誤,但無論如何)。

3

它看起來像問題是由於每個孩子在打開文件進行寫入,從而導致衝突。

嘗試具有該文件名取決於等級(例如,寫入out file.txt.(rank),看看是否所有的輸出匹配

+0

謝謝你這篇文章,直到我看完這篇文章之前,我一直在撓頭,沒有取得任何進展。很簡單。 – user1072706

3

如果您已經在使用MPI,並且不願意使用seek來分割文件,而不是使用POSIX,我建議使用MPI-IO(作爲MPI2的一部分,c。 1996年左右):很好的參考是:

,並在我們的中心,我們有這個,這是我想到的第一部分是相當不錯的:

上面的代碼的MPI-IOed版本是這樣的:

#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 

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

    int rank, np; 
    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &np); 

    const int filesize = 48*1048576; //input filesize 48MB 
    const int ndoubles = filesize/(sizeof(double)*np); 
    double *localdata = malloc(ndoubles*sizeof(double)); 

    /* create a type which describes our view of the file -- 
    * in particular, just our subarray of the global array 
    */ 
    int globalsizes[1] = {filesize}; 
    int localsizes[1] = {ndoubles}; 
    int starts[1] = {ndoubles*rank}; 

    MPI_Datatype fileview; 
    MPI_Type_create_subarray(1, globalsizes, localsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &fileview); 
    MPI_Type_commit(&fileview); 

    /* read in only our data */ 
    MPI_File fpa; 
    MPI_Status status; 
    MPI_File_open(MPI_COMM_WORLD, "512_featurevec.out", MPI_MODE_RDONLY, MPI_INFO_NULL, &fpa); 

    /* note could use MPI_File_seek instead of file set view */ 
    MPI_File_set_view(fpa, (MPI_Offset)0, MPI_DOUBLE, fileview, "native", MPI_INFO_NULL); 
    MPI_File_read_all(fpa, localdata, ndoubles, MPI_DOUBLE, &status); 
    MPI_File_close(&fpa); 

    /* write out data - it will have same layout, we're just writing instead of erading*/ 

    MPI_File_open(MPI_COMM_WORLD, "output.dat", MPI_MODE_WRONLY|MPI_MODE_CREATE, MPI_INFO_NULL, &fpa); 

    /* note could use MPI_File_seek instead of file set view */ 
    MPI_File_set_view(fpa, (MPI_Offset)0, MPI_DOUBLE, fileview, "native", MPI_INFO_NULL); 
    MPI_File_write_all(fpa, localdata, ndoubles, MPI_DOUBLE, &status); 
    MPI_File_close(&fpa); 

    free(localdata); 
    MPI_Type_free(&fileview); 
    MPI_Finalize(); 

    return 0; 
} 
+0

我很快就想測量I/O的加速,因此我試圖按照我的說明對fwrite進行並行化。但我同意,MPI_IO絕對是一種更好的方式。 – jitihsk

+0

您可以以非常類似的方式使用MPI_File_seek(或MPI_File_write_at),它將具有更好的語義(例如,如果其他人移動文件指針,則不會奇怪地行爲...) –

相關問題