Параллельное программирование: Учебное пособие, страница 103

}

    }

  else

    {                /* Посылка локального значения интеграла */

MPI_Send(&integral, 1, MPI_FLOAT, dest,

                                 tag, MPI_COMM_WORLD);

    }

  if (my_rank == 0)            /* Печать результата */

{

printf(" Оценка интеграла по %d шагам\n",n );

printf(" от %f до %f равна %f\n",a,b,total );

}

MPI_Finalize();    /* Завершение работы MPI */

} /*  main  */

/*-------------------------------------------------*/

void Get_data(            /* Функция ввода a, b,  и   n */

         float*  a_ptr,     /* out */

         float*  b_ptr,     /* out */

         int*    n_ptr,     /* out */

         int     my_rank,   /* in   */

         intp       )  /* in   */

{

intsource = 0;    /* Все локальные переменные, */

int dest;    /* используемые в MPI_SEND и MPI_RECV */

  int tag;

  MPI_Status status;

  if (my_rank == 0)

    {

      printf("Введите a, b,и n\n");

      scanf("%f %f %d", a_ptr, b_ptr, n_ptr);

      for (dest = 1; dest < p; dest++)

{

tag = 0;

/* Значение a_ptr рассылается процессорам */

/* с циклически изменяемым рангом dest */

/* и неизменной меткойtag=0,1,2 для   */

/* переменныхa_ptr, b_ptr, n_ptr*/

MPI_Send(a_ptr, 1, MPI_FLOAT, dest, tag,

                                   MPI_COMM_WORLD);

          tag = 1;                                

          MPI_Send(b_ptr, 1, MPI_FLOAT, dest, tag,

                                   MPI_COMM_WORLD);

          tag = 2;

          MPI_Send(n_ptr, 1, MPI_INT, dest, tag,

                                   MPI_COMM_WORLD);

        }

    }

  else

    {

      tag = 0;   /* Все процессоры с рангом не 0 принимают       */

/* значения переменных a_ptr, b_ptr, n_ptr */

MPI_Recv(a_ptr, 1, MPI_FLOAT, source, tag,

                             MPI_COMM_WORLD, &status);

      tag = 1;

      MPI_Recv(b_ptr, 1, MPI_FLOAT, source, tag,

                             MPI_COMM_WORLD, &status);

      tag = 2;

      MPI_Recv(n_ptr, 1, MPI_INT, source, tag,

                             MPI_COMM_WORLD, &status);

    }

} /* Get_data */

/*--------------------------------------------------*/

float Trap(                     /* Определение функции */

          float  local_a,  /* in *//* вычисляющей */

          float  local_b,  /* in *//* интеграл в       */

          int    local_n,  /* in *//* локальных       */

          float  h       ) /* in *//* пределах          */

{

  float integral;   /* Store result in integral  */

  floatx;

inti;

floatf(floatx);   /* Объявление интегрируемой функции */

integral = (f(local_a) + f(local_b))/2.0;

  x = local_a;

  for (i = 1; i <= local_n-1; i++)

    {

      x = x + h;

      integral = integral + f(x);

    }

  integral = integral*h;

  return integral;

} /*  Trap  */

/*--------------------------------------------------*/

float f(float x)       /* Определение интегрируемой функции. */

{                      /* В примере задана функция   f(x)=x*x    */

float return_val;

  return_val = x*x;

  returnreturn_val;

}

5.3  Коллективный обмен данными

При выполнении коллективного обмена сообщение пересылается от одного процесса нескольким процессам или в один процесс пересылаются данные из нескольких процессов. MPI поддерживает несколько видов коллективного обмена. При использовании коллективных обменов необходимо иметь в виду некоторые свойства и ограничения. Так, в любом коллективном обмене участвую лишь процессы в организованной для них области взаимодействия. Для создания новых областей взаимодействия имеются средства создания таких областей, которые называются коммуникаторами. Особенности коллективных обменов состоят в том, что

·  коллективный обмен не может взаимодействовать с двухточечным, например, его пересылки сообщений не перехватываются двухточечной подпрограммой приема;

·  коллективные обмены могут выполняться с синхронизацией и без нее;

·  все коллективные обмены являются блокирующими для инициировавшего их обмена;