2

char と double のシーケンスを含むバイナリ ファイルを読み込もうとしています。(たとえば、0 0.125 1 1.4 0 2.3 1 4.5 ですが、バイナリ ファイルに書き込まれます)。単純な構造体入力を作成し、この構造体に対応する mpi_input と呼ぶ MPI データ型も作成しました。

typedef struct { char type; double value } input;

を使用して、ファイルを並行して(つまり、ここでは異なるプロセッサを使用して)読みたいと思いますMPI_File_read_at_all。この関数でデータ型 mpi_input を使用したいと思います。

問題は、この関数には最後まで書き込むバッファが必要だと思うことです。を使用してみましたinput *bufferが、これにより、データ構造のアライメントが原因で問題が発生します。これを行う方法について何かアイデアはありますか?

最小限の作業例を次に示します。

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

int main(int argc, char** argv)
{
    typedef struct
    {
        double val;
        char type;
    } input;

    int rank, size;

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

    assert(size == 4);

    MPI_File in;
    MPI_Offset filesize;
    MPI_File_open(MPI_COMM_WORLD, argv[1], MPI_MODE_RDONLY, MPI_INFO_NULL, &in);
    MPI_File_get_size(in, &filesize);

    int mysize = filesize/size;
    int globalstart = rank * mysize;

    input *chunk = malloc(sizeof(input)*2);

    int n = 128;
    int m = 256;

    int blocks[2] = {1,1};
    MPI_Datatype types[2] = {MPI_BYTE, MPI_DOUBLE};
    MPI_Aint displacements[2];
    MPI_Datatype cell_type;
    MPI_Aint charex, doublex;
    displacements[0] = offsetof(input, type);
    displacements[1] = offsetof(input, val);
    MPI_Type_create_struct(2, blocks, displacements, types, &cell_type);
    MPI_Type_commit(&cell_type);

    MPI_File_read_at_all(in, globalstart, chunk, mysize, cell_type, MPI_STATUS_IGNORE);
    if(rank == 0)
        printf("0 - Got %d %f\n", chunk->val, chunk->type);
    if(rank == 4)
        printf("Got %d %f\n", chunk->val, chunk->type);

    MPI_File_close(&in);
    MPI_Finalize();
}

そして、単純なバイナリ ファイルを生成するコードを次に示します。

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

int main()
{
    FILE *fp;
    char* filename = "test.dump";
    fp = fopen(filename, "wb");

    char bla = 8;
    for(double i = 0; i < 8; i++)
    {
        fwrite(&bla, sizeof(char), 1, fp);
        bla--;
        fwrite(&i, sizeof(double), 1, fp);
    }

    fclose(fp);
}
4

1 に答える 1

4

MPI_File_read_at_all間違った引数を提供しています。MPI では、送信/受信/読み取り/書き込みされるデータに関連する引数は、ほとんどの場合、次の形式のトリプレットとして与えられますbuffer, #elements, datatype

あなたの場合、#elementsequalsmysizeはバイト単位であり、 datatype の要素数ではありませんcell_type。その結果、関数はバッファー内に収まるよりも多くの要素を読み取るため、ヒープが破損します。

代わりにすべきことはmysize、データ型のサイズで割ることです (そうではありません sizeof(input)!):

int cell_type_size;
MPI_Type_size(cell_type, &cell_type_size);

...

MPI_File_read_at_all(in, globalstart,
    chunk, mysize / cell_type_size, cell_type, MPI_STATUS_IGNORE);
//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//         data specification triplet

また、4 つの MPI プロセスの場合はからに変化するため、2 番目のprintfステートメントは決して実行されません。rank03

于 2015-11-27T20:41:45.773 に答える