2016-06-15 17 views
0

MPI I/Oを介してバイナリファイルにデータを書き込むには、MPI Cコードが必要です。私は短いヘッダーを書くためにプロセス0が必要です。そして、ヘッダーで示される配列の独自の部分を書くために全範囲のプロセスが必要です。次に、別のヘッダーを書き込むためにプロセス0が必要です。次に、すべてのプロセスが次の配列の断片を書きます。次に、実際に私が望むことをする次のテストコードを思いつきました。誰も私よりも驚くことはありません。私の質問は、私はMPI I/Oの新機能です。だから、私はそれを "得ている?私はこれを「正しい方法」としていますか、それを行うにはより効率的でコンパクトな方法がありますか?ありがとう。あなたのアプローチは結構です、あなたは、ファイル内のビットを置くために今何が必要な場合(ところで、あなたはこれをテストすると考えるならば、唯一の4つのprocsのでそれを試してみてください。)MPI I/O、シングルプロセス出力とマルチプロセス出力の組み合わせ

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

#include "mpi.h" 

#define ROWS 9 
#define COLS 10 

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

    int size_mpi, rank_mpi, row_mpi, col_mpi; 
    int i,j,p,ttlcols; 
    int sizes[]= {2*ROWS,2*COLS}; 
    int subsizes[]= {ROWS,COLS}; 
    int starts[] = {0,0}; 
    int vals[ROWS][COLS]; 
    char hdr[] = "This is just a header.\n"; 
    MPI_Status stat_mpi; 
    MPI_Datatype subarray; 
    MPI_File fh; 
    MPI_Offset offset, end_of_hdr; 
    MPI_Info info_mpi; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD,&size_mpi); 
    MPI_Comm_rank(MPI_COMM_WORLD,&rank_mpi); 

    ttlcols = 2*COLS; 
    /* Where are we in the array of processes? */ 
    col_mpi = rank_mpi%2; 
    row_mpi = rank_mpi/2; 
    /* Populate the array */ 
    for (j=0; j<ROWS; j++){ 
     for (i=0; i<COLS; i++){ 
     vals[j][i] = ttlcols*(ROWS*row_mpi + j) + 
         COLS*col_mpi + i; 
     } 
    } 
    /* MPI derived datatype for setting a file view */  
    starts[0] = row_mpi*ROWS; 
    starts[1] = col_mpi*COLS; 
    MPI_Type_create_subarray(2, sizes, subsizes, starts, 
          MPI_ORDER_C, MPI_INT, 
          &subarray); 
    MPI_Type_commit(&subarray); 
    /* open the file */  
    printf("opening file\n"); 
    MPI_File_open(MPI_COMM_WORLD, "arrdata.dat", 
       MPI_MODE_WRONLY | MPI_MODE_CREATE, 
       MPI_INFO_NULL, &fh); 
    printf("opened file\n"); 
    /* set the initial file view */  
    MPI_File_set_view(fh, 0, MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL); 
    /* proc 0 writes first header */  
    if (rank_mpi == 0) { 
     MPI_File_write(fh, (void*)hdr, strlen(hdr), MPI_CHAR, &stat_mpi); 
     MPI_File_get_position(fh, &offset); 
     MPI_File_get_byte_offset(fh, offset, &end_of_hdr); 
    } 
    /* everybody has to know where proc 0 stopped writing */  
    MPI_Bcast((void*)&end_of_hdr, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    /* re-set file view for writing first array */  
    MPI_File_set_view(fh, end_of_hdr, MPI_INT, 
        subarray, "native", 
        MPI_INFO_NULL); 
    /* and write the array */  
    MPI_File_write(fh, (void*)vals, ROWS*COLS, MPI_INT, 
        &stat_mpi); 

    /* now go through the whole thing again to test */ 
    MPI_File_get_position(fh, &offset); 
    MPI_File_get_byte_offset(fh, offset, &end_of_hdr); 
    MPI_File_set_view(fh, end_of_hdr, MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL); 
    if (rank_mpi == 0) { 
     MPI_File_write(fh, (void*)hdr, strlen(hdr), MPI_CHAR, &stat_mpi); 
     MPI_File_get_position(fh, &offset); 
     MPI_File_get_byte_offset(fh, offset, &end_of_hdr); 
    } 

    MPI_Bcast((void*)&end_of_hdr, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    MPI_File_set_view(fh, end_of_hdr, MPI_INT, 
        subarray, "native", 
        MPI_INFO_NULL); 
    MPI_File_write(fh, (void*)vals, ROWS*COLS, MPI_INT, 
        &stat_mpi); 
    MPI_File_close(&fh); 

    MPI_Finalize(); 

    return 0; 

} 
+0

あなたは常にヘッダーサイズを知っていますか?それらはすべて同じ(サイズ)ですか?その場合は、ヘッダーとデータを含むプロセス#0のビューと、データのみを含む他のプロセスのビューを作成できます。次に、ランク#0の反復ごとに 'MPI_File_set_view()'と 'MPI_File_write()'を2回呼び出すだけです。 – Gilles

+0

@ Gillesヘッダーのサイズを知っています。残念ながら、それらはすべて同じではありません。私はそれを変えることはできません。私のデザインではありません。 –

+1

あなたのコードにバグがあります: 'end_of_hdr'は' MPI_Offset'タイプで、あなたは 'MPI_INT'を使ってそれを放送しています。 'MPI_Offset'は通常64ビットですが、' MPI_INT'は 'int'に対応し、LP64 Unixシステム(* BSD、Linux、Solaris)では32ビットしかありません。ビッグエンディアンシステムでは、非常に間違ったオフセットがブロードキャストされます。 'MPI_OFFSET'(MPI実装でサポートされている場合)または対応するCタイプ(' mpi.h'を確認してください)を使用してください。 –

答えて

1

、先に行くとコール:コードですあなた自身がやった。ここで

は、より効率のためにいくつかの提案です:

  • あなたが代わりに位置を取得し、バイトに変換する、何バイト書き込まれたのかのステータスオブジェクトを参照してくださいすることができます。

  • 書き込みする前にすべてのデータを保持するメモリを持っている場合は、MPIデータ型を使用してI/Oを記述することができます(実際は作成する苦痛に終わる可能性があります)。その後、すべてのプロセスが単一の集団コールを発行します。

  • 独立したI/Oではなく、集合I/Oを使用する必要があります。 「品質ライブラリ」は、パフォーマンスが向上していなくても同等の性能を発揮できるはずです(そうでない場合は、MPI実装で問題を引き起こす可能性があります)。

  • プロセスに書き込むデータの量が異なる場合、MPI_EXSCANは誰がどのデータを持っているかを収集する良い方法です。次に、MPI_FILE_WRITE_AT_ALLをファイル内の正しいオフセットに呼び出すことができます。

+0

ありがとう! Re:あなたの3番目の弾丸、私は1つのprocには、ヘッダーを書くだけです。私はMPI_File_writeへの呼び出しを隔離することなくそれを行う方法を理解することができませんでした。誰もがMPI_File_writeを呼び出す方法はありますか?実際には1つのprocしか書いていませんか?再度、感謝します! –

+1

は絶対に。 N個のプロセスが集合的な操作を呼び出すのは公正ですが、それらのうちの1つだけがデータを持っています。どのプロセスも 'count'パラメータに0を渡すことができます。しかし、私は、ランク0がヘッダーを配列に書き込む一方で、他のすべてが配列の一部を書き込む単一の集合体を提案していました。 –

+0

が分かります。もう一度ありがとう。 –

関連する問題