MPI_OP_Create функция - PullRequest
       7

MPI_OP_Create функция

0 голосов
/ 01 марта 2020

Я хочу написать функцию, которая будет сравнивать числа из всех процессов и возвращать минимальные (число должно быть положительным).

void findIndexForMinNorm(double *invec, double *inoutvec, int *, MPI_Datatype *){
   if(invec[0] > 0){
      if(inoutvec[0] > invec[0] || inoutvec[0] < 0){
         inoutvec[0] = invec[0];
        /*inoutvec[1] = invec[1];*/
      }
   }

}

inoutve c является общим для всех процессов или нет?

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Я думаю, что это проще всего проиллюстрировать с помощью некоторого кода. Как объяснил Жиль, MPI позаботится обо всех коммуникациях и сократит процессы - все, что вам нужно указать, - это функция парного сравнения. Обратите внимание, что прототип для операции сокращения фиксируется MPI и допускает уменьшение вектора: третий аргумент - это число для длины вектора в каждом процессе ( не число процессов, которое неявно является размер коммуникатора). Кроме некоторых мелких проблем с пустыми и двойными указателями, ваша функция сравнения может быть зарегистрирована как есть и использоваться для операции сокращения:

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

void findminnorm(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype)
{
  int i;

  double *invecdble    = (double *) invec;
  double *inoutvecdble = (double *) inoutvec;

  for (i=0; i < *len; i++)
    {
      if (invecdble[i] > 0)
      {
        if (inoutvecdble[i] > invecdble[i] || inoutvecdble[i] < 0)
          {
            inoutvecdble[i] = invecdble[i];
          }
       }
    }
}


#define N 2

int main()
{
  int i;
  double input[N], output[N];

  int rank, size;
  MPI_Op MPI_MINNORM;

  MPI_Init(NULL,NULL);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  MPI_Op_create(findminnorm, 1, &MPI_MINNORM);

  for (i=0; i < N; i++)
    {
      input[i] = (-size/2+rank+i)*(i+1);
      printf("On rank %d,  input[%d] = %f\n", rank, i, input[i]);
      output[i] = -1;
    }

  MPI_Allreduce(&input, &output, N, MPI_DOUBLE, MPI_MINNORM, MPI_COMM_WORLD);

  for (i=0; i < N; i++)
    {
      printf("On rank %d, output[%d] = %f\n", rank, i, output[i]);
    }

  MPI_Finalize();
}

Инициализация немного случайна, но я думаю, что она служит для иллюстрации (хотя ваша функция сравнения должна действительно справляться с ситуацией, когда все входы отрицательны):

mpirun -n 5 ./minnorm | grep input | sort
On rank 0,  input[0] = -2.000000
On rank 0,  input[1] = -2.000000
On rank 1,  input[0] = -1.000000
On rank 1,  input[1] = 0.000000
On rank 2,  input[0] = 0.000000
On rank 2,  input[1] = 2.000000
On rank 3,  input[0] = 1.000000
On rank 3,  input[1] = 4.000000
On rank 4,  input[0] = 2.000000
On rank 4,  input[1] = 6.000000

mpirun -n 5 ./minnorm | grep output | sort
On rank 0, output[0] = 1.000000
On rank 0, output[1] = 2.000000
On rank 1, output[0] = 1.000000
On rank 1, output[1] = 2.000000
On rank 2, output[0] = 1.000000
On rank 2, output[1] = 2.000000
On rank 3, output[0] = 1.000000
On rank 3, output[1] = 2.000000
On rank 4, output[0] = 1.000000
On rank 4, output[1] = 2.000000
0 голосов
/ 02 марта 2020

inoutvec не является общим для всех процессов.

Ваша операция должна вычислять только inoutvec = min(invec, inoutvec), а библиотека MPI позаботится о связи и вызовет вашего оператора с соответствующим inoutvec.

Из главы 5.9.5 стандарта MPI стр. 185:

Рекомендации для разработчиков. Ниже мы наметим наивную и неэффективную реализацию MPI_REDUCE, не поддерживающую опцию in place.

MPI_Comm_size(comm, &groupsize);
MPI_Comm_rank(comm, &rank);
if (rank > 0) {
MPI_Recv(tempbuf, count, datatype, rank-1,...);
User_reduce(tempbuf, sendbuf, count, datatype);
}
if (rank < groupsize-1) {
MPI_Send(sendbuf, count, datatype, rank+1, ...);
}
/* answer now resides in process groupsize-1 ... now send to root
*/
if (rank == root) {
MPI_Irecv(recvbuf, count, datatype, groupsize-1,..., &req);
}
if (rank == groupsize-1) {
MPI_Send(sendbuf, count, datatype, root, ...);
}
if (rank == root) {
MPI_Wait(&req, &status);
}
...