У меня есть следующий простой код MPI:
#include <iostream>
#include <mpi.h>
int main() {
struct test {
int rank = 1;
double begin = 0.5;
double end = 0.5;
};
MPI_Init(NULL, NULL);
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_File fh;
MPI_Offset offset;
MPI_Status status;
MPI_Datatype TIMEDATA_DATATYPE;
// Create datatype
int blocklen[3] = {1,1,1};
MPI_Datatype type[3] = { MPI_INT, MPI_DOUBLE, MPI_DOUBLE };
MPI_Aint disp[3] = {0, 4, 12};
MPI_Type_create_struct(3, blocklen, disp, type, &TIMEDATA_DATATYPE);
MPI_Type_commit(&TIMEDATA_DATATYPE);
// Open file
offset = 20*world_rank;
MPI_File_open(MPI_COMM_WORLD, "test.bin", MPI_MODE_CREATE | MPI_MODE_WRONLY,
MPI_INFO_NULL, &fh);
// Write to file
test t1, t2;
MPI_File_write_at(fh, offset, &t1, 1, TIMEDATA_DATATYPE, &status);
MPI_File_write_at(fh, offset, &t2, 1, TIMEDATA_DATATYPE, &status);
// Close file
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}
Запустить и скомпилировать с
mpic++ Test.cpp
mpirun -n 2 a.out
Итак, в приведенном выше коде я в основном хочу дважды записать в один и тот же файл. Каждый раз с другого процесса. Данные представляют собой структуру формата int, double, double, поэтому 4+8+8=20 байт данных. У нас есть два объекта этой структуры, но оба они инициализированы одинаковыми значениями. Итак, мы записываем два блока по 20 байт данных в файл test.bin, и я ожидаю увидеть эту «симметрию» в двоичном представлении, но получаю: (Я предоставляю два разных вывода двух разных инструментов cli.)
$ xxd test.bin
00000000: 0100 0000 fe7f 0000 0000 0000 0000 e03f ...............?
00000010: 0000 e03f 0100 0000 ff7f 0000 0000 0000 ................
00000020: 0000 e03f 0000 0000 ...?....
$ hexdump test.bin
0000000 0001 0000 7ffe 0000 0000 0000 0000 3fe0
0000010 0000 0000 0001 0000 7fff 0000 0000 0000
0000020 0000 3fe0 0000 0000
0000028
Теперь, если мы посмотрим на вывод xxd, мы увидим:
Первые 20 байт:
Вторые 20 байт:
Теперь в основном, я не совсем уверен, почему двойники здесь отличаются.
Вместо:
MPI_Aint disp[3] = {0, 4, 12};
сделайте следующее:
disp[0] = offsetof(test, rank);
disp[1] = offsetof(test, begin);
disp[2] = offsetof(test, end);
не забудьте включить "#include <stddef.h>
" и адаптировать смещение (т.е. offset = sizeof(test) * world_rank;
)
Не пытайтесь вручную жестко закодировать смещения, лучше использовать offsetof
из <stddef.h>
, чтобы понять это за вас. Нет никакой гарантии, что отступы, используемые внутри структур, будут соответствовать значениям, которые вы жестко запрограммировали в своем массиве для смещений (т. е. disp
).
Заполнение структуры — это концепция в C, которая добавляет один или несколько пустых байтов между адресами памяти для выравнивания данных в памяти. (источник ). Чтобы лучше понять отступы, загляните в эту тему SO