2015-11-27 2 views
2

Я пытаюсь прочитать двоичный файл, содержащий последовательность символов char и double. (Например, 0 0.125 1 1.4 0 2.3 1 4.5, но записано в двоичном файле). Я создал простой ввод структуры, а также тип данных MPI, который я буду называть 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

Вы предоставляете MPI_File_read_at_all неправильные аргументы. В MPI аргументы, относящиеся к данным, которые должны быть отправлены/получены/прочитаны/записаны, почти всегда задаются как триплет следующего вида: buffer, #elements, datatype.

В вашем случае #elements равно mysize, который находится в байтах, а не в количестве элементов типа данных 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 

Кроме того, ваш второй printf заявление никогда не будет выполняться, поскольку rank варьируется от 0 - 3 в случае 4 процессов MPI.

+0

Так что это была глупая ошибка ... Большое спасибо! – waffle

Смежные вопросы