MPI_Reduce C/C++ — Сигнал: ошибка сегментации (11)

Я плохо понимаю, как MPI_Reduce работает с массивом. Мне нужно сделать поэлементную сумму.

Чтобы протестировать функцию MPI_Reduce, я написал этот простой код, и он работает:

double a[4] = {0,1,2,(double)process_id};
double b[4];
MPI_Reduce(&a, &b, 4, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);
if(id == p-1) {
    for(int i = 0; i < 4; i++){
        printf("%f, ", b[i]);
    }
}

он печатает это:

0.00000, 4.00000, 8.00000, 6.00000 

когда я запускаю этот код с 4 процессами. Оно работает!

Теперь реализую свою задачу. Предполагая, что я использую процесс p, мне нужно уменьшить p матриц размеров m * n, поэтому я переписываю каждую матрицу в виде массива

double *a;
double **A;

A = new double*[n];
//code that compute matrix A
a = (double *) malloc(m * n * sizeof(double));
int k = 0;
for(int i = 0; i < m; i++) {
    for(int j = 0; j < n; j++){
        a[k] = A[i][j];
        k++;
    }
}

Таким образом, у меня есть матрицы, которые мне нужно уменьшить в виде массива. Теперь я выполняю это сокращение:

if(id == p-1){
    reduce_storage = (double *) malloc(m * n * sizeof(double));
}

MPI_Reduce(&a, &reduce_storage, m * n, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);

Массивы a и reduce_storage распределяются одинаково, поэтому они имеют одинаковую размерность m * n, значение аргумента count MPI_Reduce. Я не понимаю, почему я пытаюсь запустить его, возвращая эту ошибку:

*** stack smashing detected ***: <unknown> terminated
[EdoardoPC:01104] *** Process received signal ***
[EdoardoPC:01104] Signal: Aborted (6)
[EdoardoPC:01104] Signal code:  (-6)
[EdoardoPC:01104] *** Process received signal ***
[EdoardoPC:01104] Signal: Segmentation fault (11)
[EdoardoPC:01104] Signal code:  (128)
[EdoardoPC:01104] Failing at address: (nil)

person Edo2610    schedule 27.02.2021    source источник


Ответы (1)


Я плохо понимаю, как MPI_Reduce работает с массивом. Мне нужно сделать поэлементную сумму.

Из источника о MPI_Reduce можно прочитать:

Сводит значения всех процессов к одному значению

int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, тип данных MPI_Datatype, MPI_Op op, int root, MPI_Comm comm)

В вашем случае MPI_Reduce будет работать как следующее изображение:

введите здесь описание изображения

(изображение взято с https://mpitutorial.com/tutorials/mpi-reduce-and-allreduce/)

Из того же источника можно прочитать:

MPI_Reduce принимает массив входных элементов для каждого процесса и возвращает массив выходных элементов корневому процессу. Выходные элементы содержат сокращенный результат.

Теперь давайте посмотрим на вашу проблему

Чтобы протестировать функцию MPI_Reduce, я пишу этот простой код, и он работает:

double a[4] = {0,1,2,(double)process_id};
double b[4];
MPI_Reduce(&a, &b, 4, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);

Все параметры правильные; &a и &b соответствуют const void *sendbuf и void *recvbuf соответственно. То же самое относится и к остальным параметрам, а именно int, MPI_Datatype, MPI_Op, int и MPI_Comm.

В этом контексте наличие a и b или &a и &b соответственно то же самое. То же самое в том смысле, что a и &a дают один и тот же адрес памяти. Несмотря на это, существуют важные различия между использованием a и &a, для подробного объяснения прочитайте следующее разница между "массивом" и "&массивом".

Массив a и reduce_storage распределяются одинаково, поэтому они имеют одинаковую размерность m * n, значение аргумента count MPI_Reduce. Я не понимаю, почему я пытаюсь запустить его, возвращая эту ошибку:

Во втором звонке

MPI_Reduce(&a, &reduce_storage, m * n, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);

Аргументы a и reduce_storage теперь имеют тип double*, и вы передаете &a и &reduce_storage в качестве аргумента MPI_Reduce. Это неправильно, потому что &a и &reduce_storage вернут адрес переменной a и reduce_storage соответственно, которая будет указателем на указатель-двойник.

Предполагая, что я использую процесс p, мне нужно уменьшить p

Боковое примечание: использование «p» в качестве общего количества размеров немного сбивает с толку, лучшим именем IMO будет total_processes, number_of_processes или что-то в этом роде.

person dreamcrash    schedule 27.02.2021