2012-03-19 9 views
5

私は巨大な行列をいくつかの部分行列に分けて計算しました。これらの計算の後、後処理のためにその行列を単一のファイルに書き込む必要があります。結果を単一のテキストファイルに書き込むことは可能ですか?どのようにすればいいですか? たとえば、y方向に分割されたnx ny行列があります(各プロセスはnxランク行列を持ちます).nx * ny行列を1つのテキストファイルに書きたいとします。mpiを使って単一のtxtファイルに行列を書き込む

+2

は、MPI-IO http://beige.ucs.indiana.edu/I590/node86.html –

答えて

12

大量のデータをテキストとして書き込むことはお勧めできません。それは実際には本当に遅く、不必要に大きなファイルを生成し、対処するのが苦痛です。大量のデータはバイナリ形式で記述し、人間の要約データのみをテキストとして記述します。コンピュータが簡単に処理できるものを作り、あなたが実際に座って扱いやすいもの(例えば、テキスト)を読み込みます。

テキストまたはバイナリとして書き込むかどうかにかかわらず、MPI-IOを使用してファイルへの出力を調整して1つの大きなファイルを生成することができます。このトピックに関する少しのチュートリアル(MPI-IO、HDF5、およびNetCDFを使用)hereがあります。 MPI-IOでは、ファイルのグローバルレイアウトに関してデータのローカルレイアウトを記述するタイプ(ここではサブアレイ)を定義し、それを「ビュー」としてファイルに書き込む方法があります。各ファイルはそれ自身のビューしか見ることができず、MPI-IOライブラリは出力を調整するので、ビューが重なり合わない限りすべてが1つの大きなファイルとして出力されます。

これをバイナリで書いていたのであれば、私たちはMPI_Writeを私たちのデータに指摘し、それを使って終了します。テキストを使用しているので、データを文字列に変換する必要があります。私たちは通常通りに配列を定義しますが、MPI_FLOATsではなく、数字ごとにcharspernum文字の新しいタイプです。

コードは次のとおりです。

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

float **alloc2d(int n, int m) { 
    float *data = malloc(n*m*sizeof(float)); 
    float **array = malloc(n*sizeof(float *)); 
    for (int i=0; i<n; i++) 
     array[i] = &(data[i*m]); 
    return array; 
} 

int main(int argc, char **argv) { 
    int ierr, rank, size; 
    MPI_Offset offset; 
    MPI_File file; 
    MPI_Status status; 
    MPI_Datatype num_as_string; 
    MPI_Datatype localarray; 
    const int nrows=10; 
    const int ncols=10; 
    float **data; 
    char *const fmt="%8.3f "; 
    char *const endfmt="%8.3f\n"; 
    int startrow, endrow, locnrows; 

    const int charspernum=9; 

    ierr = MPI_Init(&argc, &argv); 
    ierr|= MPI_Comm_size(MPI_COMM_WORLD, &size); 
    ierr|= MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    locnrows = nrows/size; 
    startrow = rank * locnrows; 
    endrow = startrow + locnrows - 1; 
    if (rank == size-1) { 
     endrow = nrows - 1; 
     locnrows = endrow - startrow + 1; 
    } 

    /* allocate local data */ 
    data = alloc2d(locnrows, ncols); 

    /* fill local data */ 
    for (int i=0; i<locnrows; i++) 
     for (int j=0; j<ncols; j++) 
      data[i][j] = rank; 

    /* each number is represented by charspernum chars */ 
    MPI_Type_contiguous(charspernum, MPI_CHAR, &num_as_string); 
    MPI_Type_commit(&num_as_string); 

    /* convert our data into txt */ 
    char *data_as_txt = malloc(locnrows*ncols*charspernum*sizeof(char)); 
    int count = 0; 
    for (int i=0; i<locnrows; i++) { 
     for (int j=0; j<ncols-1; j++) { 
      sprintf(&data_as_txt[count*charspernum], fmt, data[i][j]); 
      count++; 
     } 
     sprintf(&data_as_txt[count*charspernum], endfmt, data[i][ncols-1]); 
     count++; 
    } 

    printf("%d: %s\n", rank, data_as_txt); 

    /* create a type describing our piece of the array */ 
    int globalsizes[2] = {nrows, ncols}; 
    int localsizes [2] = {locnrows, ncols}; 
    int starts[2]  = {startrow, 0}; 
    int order   = MPI_ORDER_C; 

    MPI_Type_create_subarray(2, globalsizes, localsizes, starts, order, num_as_string, &localarray); 
    MPI_Type_commit(&localarray); 

    /* open the file, and set the view */ 
    MPI_File_open(MPI_COMM_WORLD, "all-data.txt", 
        MPI_MODE_CREATE|MPI_MODE_WRONLY, 
        MPI_INFO_NULL, &file); 

    MPI_File_set_view(file, 0, MPI_CHAR, localarray, 
          "native", MPI_INFO_NULL); 

    MPI_File_write_all(file, data_as_txt, locnrows*ncols, num_as_string, &status); 
    MPI_File_close(&file); 

    MPI_Type_free(&localarray); 
    MPI_Type_free(&num_as_string); 

    free(data[0]); 
    free(data); 

    MPI_Finalize(); 
    return 0; 
} 

ランニング与える:

$ mpicc -o matrixastxt matrixastxt.c -std=c99 
$ mpirun -np 4 ./matrixastxt 
$ more all-data.txt 
    0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 
    0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 
    1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 
    1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 
    2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 
    2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
+0

感謝を見てくださいあなたはあなたの答えです。 – peaceman

+0

私はちょうどあなたのプレゼンテーションを通して、非常に有益かつ直感的でした!ありがとうございました – solalito

関連する問題