Создание параллельных программ
Презентацию к лекции Вы можете скачать здесь.
Возможности
- Автопараллелизация.
- Использование директив.
- Языковые средства.
- 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