MPI_Scatter и MPI_Reduce

VladimirML

Здравствуйте. Помогите, пожалуйста, решить задачу.На процессе с номером "0" задать целочисленный массив X размерности n=16. С помощью функций MPI_SCATTER разослать по 4-м процессам фрагменты этого массива. Каждый процесс печатает полученные данные. Произвести сложение всех элементов массива, распределенных по процессам, с помощью функций MPI_REDUCE на процессе с номером "2".Результат напечатать.Вот, что я написал:
#include <stdio.h>
#include <mpi.h>
const int n=16;
main(int argc, char **argv)
{int i,rank,size,rc,root=0,k,x[n],y[n],z;
MPI_Comm comm;
rc=MPI_Init(&argc,&argv);
comm=MPI_COMM_WORLD;
rc=MPI_Comm_size(comm,&size);
rc=MPI_Comm_rank(comm,&rank);
int m=n/size;
if(rank==root) { printf("root = %i x=\n",rank);
for(k=0;k<n;k++){x[k]=k+1; printf("%4i",x[k]);}printf("\n");}
rc=MPI_Scatter(&x,m,MPI_INT,&y,m,MPI_INT,root,comm);
printf("process = %i y=\n",rank);
for(k=0;k<m;k++) printf("%4i",y[k]);printf("\n");
rc=MPI_Reduce(&y,&z,n,MPI_INT,MPI_SUM,2,comm);
printf("root = %i z=",2);
printf("%4i",z);printf("\n");
rc=MPI_Finalize();}
Вывод программы:
root = 0 x=
   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
process = 1 y=
   5   6   7   8
root = 2 z=   0
process = 0 y=
   1   2   3   4
root = 2 z=   0
process = 2 y=
   9  10  11  12
process = 3 y=
  13  14  15  16
root = 2 z=  28
root = 2 z=   0
28 - это сумма чисел от 1 до 7. А должно быть 136 (сумма чисел от 1 до 16). Подскажите, пожалуйста, что я делаю не так?
4 ответа

VladimirML

28 - это сумма чисел от 1 до 7
Нет, это 1+5+9+13Ты сложил именно эти числа. и ещё (n-1) число пометил чётр знает куда.http://rsusu1.rnd.runnet.ru/tutor/method/m2/page13.htmlЗ.Ы.: И ты забыл сложить полученные куски массива.


VladimirML

AlexVRud, огромное спасибо. Разобрался. Выглядеть будет так:
#include <stdio.h>
#include <mpi.h>
const int n=16;
main(int argc, char **argv)
{int i,rank,size,rc,root=0,k,x[n],y[n],z[n],sum;
MPI_Comm comm;
rc=MPI_Init(&argc,&argv);
comm=MPI_COMM_WORLD;
rc=MPI_Comm_size(comm,&size);
rc=MPI_Comm_rank(comm,&rank);
int m=n/size;
if(rank==root) { printf("root = %i x=\n",rank);
for(k=0;k<n;k++){x[k]=k+1; printf("%4i",x[k]);}printf("\n");}
rc=MPI_Scatter(&x,m,MPI_INT,&y,m,MPI_INT,root,comm);
printf("process = %i y=\n",rank);
for(k=0;k<m;k++) printf("%4i",y[k]);printf("\n");
rc=MPI_Reduce(&y,&z,m,MPI_INT,MPI_SUM,2,comm);
if(rank==2){printf("root = %i z=",rank);
for(k=0;k<m;k++) printf("%4i",z[k]);printf("\n");}
sum=0;
if (rank==2)
for (i=0;i<m;i++)
{sum=z[i]+sum;}
printf("sum= %i", sum);
rc=MPI_Finalize();}
Вывод программы:
root = 0 x=
   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
process = 0 y=
   1   2   3   4
process = 2 y=
   9  10  11  12
process = 3 y=
  13  14  15  16
process = 1 y=
   5   6   7   8
root = 2 z=  28  32  36  40
sum= 0sum= 0sum= 0sum= 136


VladimirML

VladimirML:
  1. Ты явно не понял задания, сложение частей массива надо было проводить в каждом из процессов отдельно, а то у тебя получается все сложения проводит только один принимающий узел.
  2. Твой код ужасно отформатирован (без clang-format я его не смог прочесть)
  3. Само задание ужасно, оно ни сколько не даёт понимания об MPI
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
 
const int n = 16;
const int root = 0;
 
int main(int argc, char **argv)
{
  int i;
  int m;
  int rank;
  int size;
  int *x = NULL;
  int *y = NULL;
  int sum_part = 0;
  int sum = 0;
 
  MPI_Comm comm = MPI_COMM_WORLD;
 
  MPI_Init(&argc, &argv);
  MPI_Comm_size(comm, &size);
  MPI_Comm_rank(comm, &rank);
 
  if (rank == root) {
    x = (int *)malloc(n * sizeof(int));
    printf("root = %i x=\n", rank);
    for (i = 0; i < n; i++) {
      x[i] = i + 1;
      printf("%4i", x[i]);
    }
    printf("\n");
  }
 
  m = n / size;
  y = (int *)malloc(m * sizeof(int));
 
  MPI_Scatter(x, m, MPI_INT, y, m, MPI_INT, root, comm);
 
  printf("process = %i y=\n", rank);
  for (i = 0; i < m; i++) {
    sum_part += y[i]; /* <<<<<<<<<<<<<<<<<<< Сложение делаем в каждом из процессов */
    printf("%4i", y[i]);
  }
  printf("\n");
 
  MPI_Reduce(&sum_part, &sum, 1, MPI_INT, MPI_SUM, 2, comm);
 
  if (rank == 2) {
    printf("root = %i sum= %d\n", rank, sum);
  }
 
  if (rank == root) {
    free(x);
  }
 
  free(y);
  MPI_Finalize();
  return 0;
}


VladimirML

Ты явно не понял задания, сложение частей массива надо было проводить в каждом из процессов отдельно, а то у тебя получается все сложения проводит только один принимающий узел.
Не знаю, понял ли я задание, не понял или понял не правильно, но сегодня у меня приняли работу.
Твой код ужасно отформатирован (без clang-format я его не смог прочесть)
Не спорю. Я набирал код в mc, особо его и не отформатируешь, да и у меня не было такой цели.
Само задание ужасно, оно ни сколько не даёт понимания об MPI
Уж в этом я точно не виноват. Передо мной стояла задача написать программу, я ее написал. Не без вашей помощи, за что вам огромное спасибо.За приложенный вами код отдельное спасибо. Я его разобрал. Мне было интересно.