Максимальная длина сообщения 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 3

1 ответ:

Это известная проблема в открытом MPI, которая возникает, когда коллективная операция использует совпадающие подписи, но разные типы данных (например, один вектор с одной стороны, и несколько элементов с другой стороны).

Самый простой способ обойти эту проблему-отключить модуль coll/tuned

mpirun --mca coll ^tuned -np 8 ./test 751 750

Другой вариант-переписать код и использовать другой производный тип данных, описывающий строку (вместо использования элементов m)