Как использовать MPI_Bcast и MPI_Gather в функции

#c #parallel-processing #mpi

#c #параллельная обработка #mpi

Вопрос:

Я новичок в MPI и пытаюсь научиться использовать MPI_Bcast и MPI_Gather внутри функции. Если я напишу код без использования функции следующим образом, он будет работать нормально и выдаст правильный результат:
Вывод результата в конце:
localdata[0]:19, localdata[1]:19, localdata[2]:20, localdata[3]:20, localdata[4]:21, localdata[5]:21, localdata[6]:22, localdata[7]:22,

Для компиляции и запуска на 4 процессорах использовались следующие команды:
:$ mpicc test.c -o test
:$ mpirun -np 4 test

 #include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {

    MPI_Init(amp;argc, amp;argv);
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, amp;world_rank);
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, amp;world_size);


    int i, total;
    int arr[20];
    int localdata[8];
    if (world_rank == 0) 
    {
        for(i=0;i<20;i  )
            arr[i]=i;       

        MPI_Bcast( amp;arr, 20, MPI_INT, 0, MPI_COMM_WORLD );

        printf("nn* At Process %d receivedn", world_rank);   
        for(i=0;i<20;i  )
        {
            printf("ARR[%d]:%d, ",i, arr[i]);
            total=arr[i] world_rank;
        }
        printf("n");
        localdata[0]=total;
        localdata[1]=total;

        MPI_Gather(localdata, 2, MPI_INT, localdata, 2, MPI_INT,0, MPI_COMM_WORLD);

        printf("nnPrinting Result at the end:n");
        for(i=0;i<8;i  )
        {
            printf("localdata[%d]:%d, ",i, localdata[i]);
        }
        printf("nn");
    } 
    else
    {   
        MPI_Bcast( amp;arr, 20, MPI_INT, 0, MPI_COMM_WORLD );

        printf("nn* At Process %d receivedn", world_rank);   
        for(i=0;i<20;i  )
        {
            printf("ARR[%d]:%d, ",i, arr[i]);
            total=arr[i] world_rank;
        }
        printf("n");
        localdata[0]=total;
        localdata[1]=total;

        MPI_Gather(localdata, 2, MPI_INT, localdata, 2, MPI_INT,0, MPI_COMM_WORLD);
    }


    MPI_Finalize();
    return 0;
}
  

Когда я помещаю эти коды в вызываемую функцию function_cal , она выдает мне следующую ошибку:
*** Process received signal ***
Signal: Segmentation fault (11)
Signal code: Address not mapped (1)
Failing at address: 0x7fffdeb18040
Ниже приведен код после помещения MPI_Bcast и MPI_Gather в функцию. Любая помощь будет высоко оценена.

 #include <mpi.h>
#include <stdio.h>

void function_cal(int arr[20], int localdata[8], int world_rank)
{
    int i, total;

    MPI_Bcast( amp;arr, 20, MPI_INT, 0, MPI_COMM_WORLD );

    printf("nn* At Process %d receivedn", world_rank);   
    for(i=0;i<20;i  )
    {
        printf("ARR[%d]:%d, ",i, arr[i]);
        total=arr[i] world_rank;
    }
    printf("n");
    localdata[0]=total;
    localdata[1]=total;

    MPI_Gather(localdata, 2, MPI_INT, localdata, 2, MPI_INT,0, MPI_COMM_WORLD);     
}

int main(int argc, char** argv) {

    MPI_Init(amp;argc, amp;argv);
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, amp;world_rank);
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, amp;world_size);


    int i;
    int arr[20];
    int localdata[8];
    if (world_rank == 0) 
    {
        for(i=0;i<20;i  )
            arr[i]=i;       

        function_cal(arr, localdata, world_rank);

        printf("nnPrinting Result at the end:n");
        for(i=0;i<8;i  )
        {
            printf("localdata[%d]:%d, ",i, localdata[i]);
        }
        printf("nn");
    } 
    else
    {   
        function_cal(arr, localdata, world_rank);
    }


    MPI_Finalize();
    return 0;
}
  

Комментарии:

1. Я не понимаю почему, но изменение MPI_Bcast(amp;arr …); на MPI_Bcast(arr …); внутри функции устраняет вашу проблему. Обычно вы могли бы поменять местами arr и amp;arr, поскольку они оба указывают на первый элемент массива. Похоже, это не тот случай, когда массив является параметром функции.

2. @jahed, arr и amp;arr не взаимозаменяемы. arr и amp;arr[0] являются. amp;arr является указателем на массив и имеет иную семантику, чем указатель на первый элемент, на который распадается имя массива. Кроме того, когда arr является формальным параметром, amp;arr это адрес в стеке, где хранится указатель на фактический аргумент.

3. Другая проблема заключается в том, что вы используете localdata как на отправляющей, так и на принимающей стороне MPI_Gather() , что явно запрещено стандартом MPI. Если вы хотите это сделать, то используйте MPI_IN_PLACE в качестве буфера отправки.

4. Спасибо за все ваши комментарии и рекомендации. Все они были полезны.