1 1 Простейшие параллельные программы

Рассмотрим классический пример задачи: программу "Hello world". Программа может быть запущена в среде MPI на произвольном количестве процессоров. Каждая копия программы, будучи запущена на своем узле кластера, перчатает приветствие, номер процесса, вызвавшего функцию печати и общее количество процессов.

Текст программы следующий:

  1. program hello
  2. include 'mpif.h'
  3. integer rank, size, ierr
  4.  
  5. call MPI_INIT(ierr)
  6. call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
  7. call MPI_COMM_SIZE(MPI_COMM_WORLD,size,ierr)
  8.  
  9. print *,"Hello world! I am ",rank," of ",size
  10.  
  11. call MPI_FINALIZE(ierr)
  12. stop
  13. end
  14.  

Теперь рассмотрим более осмысленную задачу. Возьмем за основу вычисление числа . Число pi будем вычислять как определенный интеграл :

Согласно правилу прямоугольников интеграл можно заменить суммой:

Теперь посмотрим как этот алгоритм можно реализовать на языке FORTRAN в многопроцессорном параллельном варианте, с использованием системы MPI: pi-mpi.f

  1. program calc_pi
  2. include 'mpif.h'
  3. integer i, n
  4. double precision w, gsum, sum
  5. double precision v
  6. integer np, myid, ierr
  7. real*8 time, mflops, time1, time2, dsecnd
  8. c Инициализация MPI и определение процессорной конфигурации
  9. call MPI_INIT( ierr )
  10. call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
  11. call MPI_COMM_SIZE( MPI_COMM_WORLD, np, ierr )
  12. c Информацию с клавиатуры считывает 0-й процессор
  13. if ( myid .eq. 0 ) then
  14. n = 400000000
  15. time1 = MPI_Wtime()
  16. endif
  17. c Рассылка числа точек разбиения всем процессорам
  18. call MPI_BCAST(n, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
  19. c Вычисление частичной суммы на процессоре
  20. w = 1.0 / n
  21. sum = 0.0d0
  22.  
  23. c Вычисление процессом своей части суммы
  24. do i = myid+1, n, np
  25. v = (i - 0.5d0 ) * w
  26. v = 4.0d0 / (1.0d0 + v * v)
  27. sum = sum + v
  28. end do
  29. c Суммирование частичных сумм с сохранением результата в 0-м
  30. c процессоре
  31. call MPI_REDUCE(sum, gsum, 1, MPI_DOUBLE_PRECISION,
  32. $ MPI_SUM, 0, MPI_COMM_WORLD, ierr)
  33. c Печать выходной информации с 0-го процессора
  34. if (myid .eq. 0) then
  35. time2 = MPI_Wtime()
  36. time = time2 - time1
  37. mflops = 9 * n / (1000000.0 * time)
  38. print *, 'pi is approximated with ', gsum *w
  39. print *, 'time = ', time, ' seconds'
  40. print *, 'mflops = ', mflops, ' on ', np, ' processors'
  41. print *, 'mflops = ', mflops/np, ' for one processor'
  42. endif
  43. c Закрытие MPI
  44. call MPI_FINALIZE(ierr)
  45. end
  46.  

Copyright © 1998-2011 Юрий Сбитнев