Максимальная длина сообщения MPI Type vector и MPI Gather
Я получаю сообщение об ошибке "ошибка произошла в 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 (R) Core (TM) i7-4790K CPU @ 4.00 GHz
ОПЕРАТИВНАЯ ПАМЯТЬ: 8 ГБ
ОС: Windows 10 Home 64-bit
Компилятор: 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
1 ответ:
Это известная проблема в открытом MPI, которая возникает, когда коллективная операция использует совпадающие подписи, но разные типы данных (например, один вектор с одной стороны, и несколько элементов с другой стороны).
Самый простой способ обойти эту проблему-отключить модуль
coll/tuned
mpirun --mca coll ^tuned -np 8 ./test 751 750
Другой вариант-переписать код и использовать другой производный тип данных, описывающий строку (вместо использования элементов
m
)