Этот блок изменяет характеристики эффективности с учетом того, что в узлах кластера теперь находятся мультипроцессоры.
DVM-предиктор вычисляет достаточно много характеристик эффективности для интервала. В качестве интервала может выступать гнездо циклов, а также вся программа. Нам потребуется пересчитать только некоторые из этих характеристик:
- CPU_time_usr - полезное процессорное время – время, потраченное на выполнение вычислений в интервале.
- CPU_time_sys – полезное системное время – время, проведенное процессором в системной фазе (время, затраченное Lib-DVM).
- CPU_time – полное процессорное время. Равняется сумме CPU_time_usr и CPU_time_sys.
- Execution_time– время выполнения интервала.
Остальные характеристики пересчитываются вызовом специальных функций Библиотеки DVM-предиктора, поэтому мы их рассматривать не будем.
Указанные характеристики вычисляются для всех интервалов на каждом узле. Поядерные характеристики мы вычислять не будем.
Рассмотрим интервал, соответствующий гнезду циклов. Обозначим внешний цикл гнезда как L. Значение характеристики <Имя_ характеристики > на этом интервале на i-м узле мы будем обозначать как <Имя_характеристики>Li.Требуется пересчитать эти поузловые характеристики с учетом того, что в каждом узле работает по несколько ядер. Поядерные характеристики не высчитываются.
Алгоритм выполняет весьма приближенную оценку характеристик эффективности DVM/OpenMP-варианта, поэтому в дальнейшем нуждается в доработке.
Будем говорить, что интервал распараллелен на OpenMP (или DVM), если этот интервал соответствует гнезду циклов, распараллеленному на OpenMP (или DVM).
Поочередно обрабатываем каждый интервал. Нас будут интересовать только те интервалы, которые распараллелены на OpenMP. Пусть текущий интервал – это гнездо циклов, распараллеленное на OpenMP. Обозначим внешний цикл гнезда за L. Выполняем следующие действия.
Шаг 1. Находим коэффициент ускорения. Коэффициент ускорения отражает во сколько раз быстрее цикл будет вычисляться на SMP-кластере, нежели на кластере с тем же количеством узлов. То есть во сколько раз полезное процессорные время DVM/OpenMP-варианта меньше соответствующего DVM-варианта. Системные затраты в расчет не берутся.
Вычисляется коэффициент ускорения следующим образом. Находим максимальное количество итераций распараллеливаемого на OpenMP цикла, которое приходится на один узел.
Затем находим, какое максимальное количество итераций этого цикла может прийтись на одно ядро этого узла. Коэффициент ускорения равняется отношению первой величины на вторую.
Шаг 2. Пересчитываем поузловые характеристики эффективности текущего интервала
· Для каждого узла кластера пересчитываем полезное процессорное время выполнения гнезда циклов, поделив старое значение параметра CPU_time_usrLi на коэффициент ускорения.
· Вычисляем для каждого узла разность между старым и новым значение параметра CPU_time_usrLi. Обозначим эту величину для i-го узла как CPU_usr_diffLi.
· Пересчитываем полное процессорное время:
CPU_timeLi := CPU_time_usrLi + CPU_time_sysLi.
· Пересчитываем время выполнения интервала. Execution_timeLi складывается из полезного процессорного времени, системных затрат, простоев и пр. Мы предполагаем, что из всех этих характеристик изменяется только полезное процессорное время, и не учитываем системные затраты на использование OpenMP, а также простои ядер и время на их синхронизацию. Для каждого узла из Execution_timeLi следует вычесть CPU_usr_diffLi.
Шаг 3. Пересчитываем характеристики эффективности интервалов, вложенных в текущий (гнезда циклов, вложенные, но не тесно-вложенные в текущее гнездо циклов). Для каждого вложенного интервала следует выполнить действия, описанные на Шаге 2.
Шаг 4. Пересчитываем характеристики эффективности интервалов, содержащих текущий интервал.
Пусть цикл L непосредственно вложен в цикл P. В качестве P может также выступать тело всей программы. Возможны два случая:
1) Цикл P является внешним для некоторого гнезда циклов или является телом всей программы. В этом случае, циклу Pсоответствует некоторый интервал, для которого DVM-предиктором подсчитаны характеристики эффективности. Эти характеристики следует пересчитать. Для каждого узла (i от 1 до Число_узлов) выполняем следующие действия:
· CPU_time_usrPi := CPU_time_usrPi - CPU_usr_diffLi
· CPU_timePi := CPU_time_usrPi + CPU_usr_sysPi
· Execution_timePi := Execution_timePi - CPU_usr_diffLi
2) Цикл P не является внешним для некоторого гнезда циклов.
Пусть Np – количество итераций цикла P. Для цикла P характеристики эффективности не вычислялись. Нам известно, что тело цикла P на i-м узле стало выполняться на CPU_usr_diffLi быстрее. Соответственно, весь цикл P будет выполняться на i-м узле быстрее на Np * CPU_usr_diffLi. Отразим этот факт следующей записью:
CPU_usr_diffPi := Np * CPU_usr_diffLi.
Если P является самым внешним циклом (телом всей программы), останавливаемся. В противном случае все действия, описанные в шаге 4, следует повторить для цикла, в который непосредственно вложен цикл P.
DVM/OpenMP-эксперт, имеет следующие ограничения:
- Входная программы должна быть написана на языке Фортран 77
- Входная программы не должна содержать процедуры или допускать их инлайн-подстановку.
- DVM/OpenMP-эксперт распараллеливает только циклы.
- На OpenMP распараллеливаются только те циклы, которые сумел распараллелить DVM-эксперт, а также циклы, тесно-вложенные в него.
Текущая версия анализатора не предоставляет DVM/OpenMP эксперту информацию об особенностях цикла. Недостающую информацию должен сообщать пользователь, используя специальные комментарии. Рассмотрим их подробнее.
Если программист хочет задать дополнительную информацию о программе, он должен вставить в текст программы комментарий, начинающийся с последовательности символов CPRG. Всё, что идёт после этих символов записывается в Базу Данных в таблицу специальных комментариев. Если требуется прокомментировать свойства какого-нибудь цикла, комментарии вставляются перед заголовком цикла.
DVM/OpenMP-эксперт обрабатывает следующие специальные комментарии:
· private(<переменная>) – задаёт переменную, для которой порождается локальная копия в каждой нити; начальные значения локальных переменной не определено.
· private_all(<переменная>) – задаёт переменную, которая будет private на протяжении всей программы.
· first_private(<переменная>) – задаёт переменную, для которой порождается локальная копия в каждой нити; локальные копии переменных инициализируются значением этой переменной в нити-мастере;.
· last_private(<переменная>) –переменной присваивается результат с последнего витка цикла;
· reduction(<переменная>(<оператор>)) - задаёт оператор и переменную; для переменной создаются локальные копии в каждой нити; локальные копии инициализируются соответственно типу оператора (для аддитивных операций – 0 или его аналоги, для мультипликативных операций – 1 или её аналоги); над локальными копиями переменной после выполнения всех операторов параллельной области выполняется заданный оператор [9]. В Таблице 1 отражено соответствие между текстовым представлением <оператор> и его аналогом на языке Fortran.
<оператор> | Оператор языка Fortran |
SUM | + |
PRODUCT | * |
MAX | Max |
MIN | Min |
AND | .and. |
OR | .or. |
EQV | .eqv. |
NEQV | .neqv. |
Таблица 1. Редукционные операции.
Рассмотрим аргументы командной строки, доступные при использовании DVM/OpenMP-эксперта.
Ключ | Описание |
-omp | Отрабатывает только OpenMP-эксперт. На выходе получаем параллельную программу для SMP-системы на языке Fortran-OpenMP. |
-dvm | Отрабатывает только DVM-эксперт. На выходе получаем параллельную программу для кластера на языке Fortran-DVM. |
-omp -dvm | Если присутствуют оба ключа (или нет ни одного из этих ключей), отрабатывает DVM/OpenMP-эксперт. На выходе получаем параллельную программу для SMP-кластера на языке Fortran-DVM/OpenMP |
-variants | Включается режим, в котором на выходе выдаются все варианты распараллеливания. Это могут быть DVM-варианты, OpenMP-варианты или DVM/OpenMP-варианты в зависимости от присутствия ключей-omp и -dvm. |
-nproc <число> | Задаем количество узлов кластера |
-ncore <число> | Задаем количество ядер, находящихся на каждом из узлов |
Таблица 2.Аргументы командной строки
Тестирование анализатора проводилось на программах, реализующих решение уравнения Пуассона в трехмерном пространстве классическими итерационными методами: методом Якоби, методом последовательной верхней релаксации (SOR), методом красно-черного упорядочения (RedBlack), а также тесте, разработанном NASA Ames Research Center (LU). В тестах Якоби, SOR и RedBlack использовалась матрица размером 3000x3000.
DVM/OpenMP-варианты, полученные на указанных тестах с помощью DVM/OpenMP-эксперта, успешно прошли проверку на инструменте IntelThreadChecker 3.1. IntelThreadChecker – инструмент для отладки параллельных программ. Он осуществляет поиск мест с возможным недетерминированным поведением многопоточной программы, написанной как на основе библиотеки потоков (Windows или POSIX threads), так и с использованием технологии OpenMP. IntelThreadChecker рассматривает DVM/OpenMP-вариант как программу на языке Fortran-OpenMP. Отметим, что IntelThreadChecker не в состоянии проверить отсутствие ошибок в работе конвейерного алгоритма.