Я получаю сообщение об ошибке «Произошла ошибка в MPI_Gather», когда я пытаюсь собрать массивы типа double с более 750 элементов в массив, который представляет собой матрицу.Предполагается, что собираемые массивы представляют столбцы матрицы, и поскольку матрица построена таким образом, что строки находятся в памяти рядом, я определил производный тип данных как вектор столбцов и назвал MPI_Gather следующим образом:
for (i = 0; i < k; i++) {
MPI_Gather(&Q_vector[i*m], m, MPI_DOUBLE, &Q[i*size], 1, vector_m, 0, MPI_COMM_WORLD);
}
где k - количество векторов, m - длина каждого вектора (количество строк в матрице), size - это числочисло процессов и vector_m - это производный тип данных, который построен следующим образом:
MPI_Type_vector(m, 1, n, MPI_DOUBLE, &vector_m_type);
MPI_Type_create_resized(vector_m_type, 0, sizeof(double), &vector_m);
MPI_Type_commit(&vector_m);
, где n - количество столбцов в матрице.
Это нормально работает до m > 750. Если, например, m = 751, возникает ошибка (751 элемент типа double).Это не зависит от значения n .Я полностью изменил алгоритм так, чтобы столбцы матрицы сохранялись последовательно в памяти, вместо этого, чтобы решить проблему, вообще избегая производного типа данных, но мне все еще любопытно, почему это происходит.
Спецификации компьютера:
Процессор: Intel® Core® TM CPU i7-4790K @ 4,00 ГГц
Оперативная память: 8 ГБ
ОС: Windows 10 Home 64-битная
Компилятор: gcc 6.4.0
Я использую Cygwin.
Это сообщение об ошибке иногда печатается:
"Произошла ошибка в MPI_Gather, о которой сообщил процесс [52635822596882433,77309411328] на коммуникаторе MPI_COMM_WORLD
MPI_ERR_IN_STATUS: код ошибки в статусе MPI_ERRORS_ARE_FATAL (процессы в этом коммуникаторе теперь прервутся и, возможно, ваша работа MPI) "
Минимальный рабочий пример кода для воспроизведения ошибки:
#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int n, m, size, rank, i, j, k;
double *Q, *Q_vector;
MPI_Datatype vector_m_type, vector_m;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
m = atoi(argv[1]);
n = atoi(argv[2]);
if (rank == 0) {
Q = (double *)malloc(m*n*sizeof(double));
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
Q[i*n+j] = drand48()*10;
}
}
}
// k = number of (column) vectors per process
k = n/size;
Q_vector = (double *)malloc(k*m*sizeof(double));
MPI_Type_vector(m, 1, n, MPI_DOUBLE, &vector_m_type);
MPI_Type_create_resized(vector_m_type, 0, sizeof(double), &vector_m);
MPI_Type_commit(&vector_m);
for (i = 0; i < k; i++) {
MPI_Scatter(&Q[i*size], 1, vector_m, &Q_vector[i*m], m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}
for (i = 0; i < k; i++) {
MPI_Gather(&Q_vector[i*m], m, MPI_DOUBLE, &Q[i*size], 1, vector_m, 0, MPI_COMM_WORLD);
}
if (rank == 0) {
printf("Success!\n");
free(Q);
}
free(Q_vector);
MPI_Finalize();
}
Скомпилирован и работает так:
mpicc -o test MPI_Type_vector_test.c -lmpi -lm
mpirun -np 8 ./test 751 750