Создание параллельных программ
Презентацию к лекции Вы можете скачать здесь.
Возможности
- Автопараллелизация.
- Использование директив.
- Языковые средства.
- CoArray для систем с распределенной памятью.
- Библиотеки MPI для систем с распределенной памятью.
- OpenMP для систем с общей памятью.
- Использование библиотек Intel-MKL.
- Сервис 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
Критерии параллелизации цикла
- Вычисляемость количества итераций цикла во время компиляции.
do ! вычисления if (условие) exit end do - Отсутствие зависимостей по данным:
- потоковой (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) разделённое глобальное адресное пространство.
Глобальная адресуемая память представлена логическими разделами. У каждого процессора свой раздел.
Цели
- Простое расширение Fortran и чувствовать, как Fortran, а не как что-то другое.
- Небольшие требования к разработчикам.
- Очевидность локальности или удаленности ссылки.
- Обеспечение возможности для оптимизации связей.
- Легкая читаемость кода.
Модель программирования
Архитектура 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

