next up previous contents
Next: Ввод / вывод для Up: Пример приложения с обменом Previous: Пример приложения с обменом   Contents

Параллелизация правила трапеции

Вариант параллелизации этой программы сводится к тому, чтобы просто разделить интервал $\left[a,b\right]$ между процессами, чтобы каждый процесс оценил интеграл $f(x)$ на своем подинтервале. Для оценки величины полного интеграла локальные значения всех процессов суммируются.

Пусть программа содержит $p$ процессов и $n$ трапеций, где $n$ является кратным $p$. Тогда первый процесс вычисляет область первых $n/p$ трапеций, второй - область следующих $n/p$ и т.д. Тогда процесс $q$ будет оценивать интеграл по интервалу


\begin{displaymath}
\left[a+q\frac{nh}{p},a+\left(q+1\right)\frac{nh}{p}\right]\end{displaymath}

Каждый процесс должен обладать следующей информацией:

Первые два пункта можно определить с помощью функций
MPI_Comm_size() и MPI_Comm_rank(). Последние два пункта вводятся пользователем. Однако это может потребовать решения некоторых дополнительных задач. Поэтому для первой попытки вычисления интеграла эти значения задаются прямо в коде программы.

Подведение итогов индивидуальных вычислений процессов состоит в том, чтобы каждый процесс посылал свое локальное значение в процесс 0, а процесс 0 производил заключительное суммирование. Новый вариант программы:

#include <stdio.h>

#include ''mpi.h''

 

float f(float x) {

  float return_val;

 

  /* Вычисляет f(x).

    Возвращает результат в return_val. */

  . . .

  return return_val;

}

 

float Trap(float local_a, float local_b, int local_n,

      float h) {

  float integral; /* Результат вычислений */

  float x;

  int i;

 

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

  x = local_a;

  for (i = 1; i <= local-n-1; i++) {

    x += h;

    integral += f(x);

  }

  integral *= h;

  return integral;

} /* Trap */

 

main(int argc, char** argv) {

  int my_rank; /* Ранг процесса */

  int p; /* Количество процессов */

  float a = 0.0; /* Левая граница */

  float b = 1.0; /* Правая граница */

  int n = 1024; /* Количество трапеций */

  float h; /* Ширина трапеции */

  float local_a; /* Левая граница для процесса */

  float local_b; /* Правая граница для процесса */

  int local_n; /* Количество вычисляемых трапеций */

  float integral; /* Значение интеграла по интервалу */

  float total; /* Общий интеграл */

  int source; /* Процесс, посылающий интеграл */

  int dest = 0; /* Пункт назначения процесс 0 */

  int tag = 50;

  MPI_Status status;

 

  MPI_Init(&argc, &argv);

  /* Определить ранг процесса */

  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  

  /* Определить количество процессов */

  MPI_Comm_size(MPI_COMM_WORLD, &p);

  h = (b-a)/n; /* h одинаково для всех процессов */

  local_n = n/p; /* Получить количество трапеций */

  

  /* Вычислить границы интервала и частный интеграл*/

  local_a = a + my_rank*local_n*h;

  local_b = local_a + local_n*h;

  integral = Trap(local_a, local_b, local_n, h);

 

  /* Суммировать все интегралы */

  if (my_rank == 0) {

    total = integral;

    for (source = 1; source < p; source++) {

       MPI_Recv(&integral, 1, MPI_FLOAT,

           source, tag, MPI_COMM_WORLD, &status);

       total += integral;

    }

  } else {

       MPI_Send(&integral, 1, MPI_FLOAT, dest,

          tag, MPI_COMM_WORLD);

  }

 

  /* Вывод результата */

  if (my_rank == 0) {

    printf(''C n = %d трапециями, оценка\n'', n);

    printf(''интеграла от %f до %f = %f`\n'',

           a, b, total);

  }

 

  /* Завершить приложение MPI */

  MPI_Finalize();

} /* main */


next up previous contents
Next: Ввод / вывод для Up: Пример приложения с обменом Previous: Пример приложения с обменом   Contents
2004-06-22