Опубликован: 18.12.2012 | Доступ: свободный | Студентов: 272 / 55 | Длительность: 03:25:00
Лекция 3:

Создание параллельных программ

< Лекция 2 || Лекция 3: 12 || Лекция 4 >
Аннотация: Лекция знакомит с возможностями в создании параллельных программ. Рассматриваются языковые средства, в частности оператор do concurrent, директивы для параллельного выполнения участков программы. Отдельно стоит отметить использование CoArray Fortran для систем с распределённой памятью.

Презентацию к лекции Вы можете скачать здесь.

Возможности

  1. Автопараллелизация.
  2. Использование директив.
  3. Языковые средства.
  4. CoArray для систем с распределенной памятью.
  5. Библиотеки MPI для систем с распределенной памятью.
  6. OpenMP для систем с общей памятью.
  7. Использование библиотек Intel-MKL.
  8. Сервис Intel Advisor, Intel Inspector.

Автопараллелизация

Auto-parallelization функция компилятора Intel® автоматически переводящая последовательные части программы в эквивалентный многопоточный код.

Последовательный код

subroutine serial(a, b, c)
  integer, dimension(100) :: a, b, c
  do i = 1,100
    a(i) = a(i) + b(i) * c(i)
  enddo
end subroutine serial
    

Параллельный код

subroutine sub_par(a, b, c)
  integer, dimension(100) :: a, b, c

  do i = 1,50 ! поток 1
    a(i) = a(i) + b(i) * c(i)
  end do

  do i = 51,100 ! поток 2
    a(i) = a(i) + b(i) * c(i)
  end do
end subroutine par
    

Критерии параллелизации цикла

  1. Вычисляемость количества итераций цикла во время компиляции.
    do 
       ! вычисления
       if (условие) exit
    end do
          
  2. Отсутствие зависимостей по данным:
    • потоковой (FLOW, READ after WRITE)
    • антизависимости (ANTI, WRITE after READ)
    • выходной (OUTPUT, WRITE after WRITE)

Директивы

Директива !DEC$ PARALLEL приводит к параллельному выполнению цикла.

Следим за зависимостью данных, ответственность на разработчике!
!DEC$ PARALLEL [ALWAYS]
    

выполнять параллельно, даже если это противоречит "решению" компилятора.

!DEC$ PARALLEL [ALWAYS [ASSERT]]
    

выдавать сообщение о невозможности распараллеливания цикла

!DEC$ NOPARALLEL
    

отмена автопараллелизации

Пример использование директив !DEC$ PARALLEL, !DEC$ NOPARALLEL

program prog
  integer, parameter :: n = 100
  integer x(n),a(n) 

  !DEC$ NOPARALLEL
  do i = 1,n
    x(i) = i
  end do 

  !DEC$ PARALLEL
  do i = 1,n
    a( x(i) ) = i
  end do
end
    

DO CONCURRENT

Организация параллельного выполнения цикла. Не должно быть зависимости по данным.

real  Q
   do concurrent (k = 1:N)
      Q = B(k) + C(k)
      D(k) = Q + sin(Q) + 2
   end do
    

COARRAY

CAF (CoArray Fortran) середина 90-х годов

Поддержка компанией Cray. Центр развития – Rice University

Модель PGAS (Partitioned Global Address Space) разделённое глобальное адресное пространство.

Глобальная адресуемая память представлена логическими разделами. У каждого процессора свой раздел.

Цели

  1. Простое расширение Fortran и чувствовать, как Fortran, а не как что-то другое.
  2. Небольшие требования к разработчикам.
  3. Очевидность локальности или удаленности ссылки.
  4. Обеспечение возможности для оптимизации связей.
  5. Легкая читаемость кода.

Модель программирования

Архитектура SPMD "Single program multiple data" ("Одна программа - много данных")

Создаётся один экземпляр программы, который затем копируется несколько раз. Каждая копия выполняется параллельно, обрабатывает свои локальные данные.

Данные распределенные между копиями программы объявляются как coarray переменные.

Подключение

В свойствах проекта указать использование Coarrays, при необходимости Coarray Images.

Images

Image - копия CAF - программы.

Функция num_images() возвращает количество созданных копий программы.

Количество копий программы как правило соответствует количеству имеющихся процессоров. В общем случае устанавливается в настройках проекта.

Каждая копия имеет свой уникальный номер, возвращаемый функцией this_image().

COARRAY - переменные

Данные распределенные между images объявляются как coarray переменные.

тип имя [*]

integer A[*] ! A[1] – переменная A 
             !        в копии № 1
             ! A[2] – переменная A 
                      в копии № 2
        
real С(N)[-1:*] ! С(N)[-1] – массив С
                !         в копии № 1
                ! С(N)[0]  – массив С
                !         в копии № 2
        
complex     Y(50)[1:10,1:*]
type (matrix)   MS[*] 
real, allocatable :: W(:)[:]
        

Пересылка данных – обращение к элементам coarrays.

complex C(100,100)[*]
        

Объявление копии массива для всех images.

C(1:10,30:50)[2] = C(21:30,90:100)[3]
        

Пересылка сечения массива из 3-й копии во 2-ю.

Если без скобок то обращение к локальному, т.е. в первой копии программы пересылка массива А в k-ю копию A[k] = A равносильно A[k] = A[1]

Для определения номера копии программы по индексам coarray используется функция image_index().

program CAF
  complex Y(50)[1,1:*]

  if (this_image() == 1) then ! == 2
    write(*,*) "This is ", this_image(),  &
               " copy of program "

    write(*,*) "Image index = ", & 
               image_index(Y, [1,this_image()])

    write(*,*) "Coordinates = ", this_image(Y)
    write(*,*)
  end if
        
 This is            1  copy of program
 Image index =            1
 Coordinates =            1           1
        

Функция lcobound возвращает нижнюю границу coarray - переменной. Функция ucobound возвращает верхнюю границу coarray - переменной.

type point
  integer x
  integer y
end type point
type (point) PS(10)[1,-2:*]
  ! num_images() = 4   ! 1   -2
  write(*,*) "LCOBOUND = ", LCOBOUND (PS)   
  write(*,*) "UCOBOUND = ", UCOBOUND (PS)    
                       ! 1    1
        
< Лекция 2 || Лекция 3: 12 || Лекция 4 >