#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. Спасибо за все ваши комментарии и рекомендации. Все они были полезны.