Средства автоматизированного распараллеливания программ
Как уже отмечалось в предыдущих разделах, средства автоматизированного распараллеливания следует использовать на первом этапе разработки параллельной программы, если у нее уже существует работающий последовательный аналог. В этом случае на первом этапе разработки параллельной программы рекомендуется применить средства автоматизированного распараллеливания к исходной последовательной программе.
В настоящее время все основные компиляторы Fortran и C/C++, предназначенные для разработки параллельных программ с использованием OpenMP, имеют возможности автоматического распараллеливания. Кроме того, эти компиляторы допускают установку различных уровней автоматического распараллеливания, а также генерируют отчеты по результатам распараллеливания.
После автоматического распараллеливания рекомендуется провести профилирование программы, и если окажется, что наиболее трудоемкие места хорошо распараллелены, то работу по созданию параллельной версии программы можно закончить. В противном случае рекомендуется воспользоваться средствами OpenMP для дальнейшего распараллеливания наиболее трудоемких участков программы. Обычно так и происходит, поскольку для сложных программ с помощью автоматического распараллеливания редко удается получить максимальный эффект. Чтобы четко разобраться в этом вопросе, далее рассмотрим некоторые основные средства автоматизированного распараллеливания и принципы их работы.
Основные средства автоматизированного распараллеливания и принципы их работы
Основным объектом автоматизированного распараллеливания с помощью специальных настроек компиляторов являются циклы. При распараллеливании циклов компилятор, во-первых, выделяет независимые по данным петли циклов. Во-вторых, он оценивает приблизительный эффект от распараллеливания цикла. Если оценка этого эффекта соответствует заданному уровню, то компилятор определяет локальные переменные. И, наконец, только затем производится само распараллеливание цикла с помощью библиотек процессов. По результатам проведенной или не проведенной работы выдается сообщение в файл отчета о распараллеливании с объяснением причин.
Как правило, других возможностей автоматизированного распараллеливания большинство компиляторов не имеет. Все это в полной мере относится к компиляторам Fortran и C/C++ компании Intel и некоторым другим. Как видим, вышеперечисленные возможности автоматизированного распараллеливания сравнительно невелики.
Отметим, что значительно более широкими возможностями в области автоматического распараллеливания обладает компилятор Fortran 95 для операционной системы Linux компании Lahey, известный под названием Lahey/Fujitsu Fortran 95 for Linux. В этом компиляторе значительно улучшен процесс оптимизации программ, а также обеспечивается поддержка аппаратных функций новых процессоров. Кроме того, поддерживается автоматическое распараллеливание и дополнительные инструкции SSE2 для процессоров Intel Xeon и Pentium IV. Компилятор Fortran Lahey/Fujitsu занимает одну из лидирующих позиций в областях, где необходимы большие объемы математических вычислений и осуществляется работа с большими массивами. Этот компилятор осуществляет автоматическое распараллеливание программ, в том числе и с использованием OpenMP версии 2.0. Оптимизация программ осуществляется для процессоров как компании Intel, так и компании AMD, при этом поддерживается оптимизация конвейера упреждающей выборки. Кроме того, для отладки параллельных программ компилятор совместим с параллельным отладчиком TotalView.
Кроме компиляторов существуют и более продвинутые программные системы в области автоматизированного распараллеливания.
В качестве примера отметим программный продукт Bert77, разрабатываемый компанией Paralogic. Программа Bert77 автоматически распараллеливает Fortran-программы в средах PVM или MPI. Распараллеливание осуществляется с использованием механизма обмена сообщениями. Программа Bert77 - это коммерческий продукт, однако существует и его упрощенная бесплатная версия (lite-версия).
В подразделении компании Intel - KAI Software Lab (бывшая Kuck & Associates Inc.) разработаны и продолжают совершенствоваться:
- KAP/Pro Toolset - набор программных средств для распараллеливания больших расчетных программ на параллельных вычислительных системах с общей памятью;
- KAI C++ - компилятор С/C++ с широкими возможностями оптимизации и распараллеливания;
- Visual KAP - программа автоматического распараллеливания Fortran-программ в режиме визуального диалога;
- Visual KAP для OpenMP - инструмент визуальной генерации программ с использованием OpenMP.
Компания Applied Parallel Research Inc. предлагает программу spf, автоматически распараллеливающую программы для параллельных вычислительных систем с общей памятью с применением OpenMP или POSIX.
Компания Pacific-Sierra Research разработала интересные и очень эффективные средства:
- VAST/Parallel - программу автоматического распараллеливания программ на языках Fortran и C/C++ для параллельных вычислительных систем с общей памятью с использованием OpenMP;
- VAST/toOpenMP - программу, автоматически распознающую параллелизм и генерирующую директивы OpenMP в программах на языке Fortran.
Отметим также разработанную этой компанией среду проектирования, отладки и анализа производительности параллельных программ в системах с распределенной и общей памятью DEPP (Development Environment for Parallel Programs), реализующую директивы OpenMP.
Существует и еще целый ряд других средств автоматизированного распараллеливания, однако здесь были перечислены лишь те средства, которые осуществляют автоматическое распараллеливание с использованием OpenMP.
Автоматическое распараллеливание программ с помощью компиляторов Intel
Рассмотрим возможности автоматического распараллеливания программ с применением современных компиляторов компании Intel. Отметим, что в компиляторах Intel реализована только одна принципиальная возможность распараллеливания: это создание многопоточных приложений распараллеливанием цикла с помощью библиотек процессов.
Далее рассмотрим подробнее настройки режима автоматического распараллеливания, имеющиеся в компиляторах Fortran и С/C++ компании Intel:
- -parallel - эта настройка позволяет компилятору автоматически создавать многопоточные версии программ с безопасным распараллеливанием циклов (подчеркнем, что кроме циклов в этом режиме больше ничего не распараллеливается);
- -par_report{0|1|2|3} - эта настройка позволяет создавать отчеты различного уровня - 0, 1, 2 или 3 (наиболее подробный отчет имеет уровень 3) по результатам автоматического распараллеливания. Рекомендуется тщательно анализировать такие отчеты, чтобы четко понять, какие еще места программы могли бы быть распараллелены и почему это не было сделано. Возможно, компилятору не хватило информации для принятия решения о распараллеливании такого участка программы. В этом случае это можно сделать вручную;
- -par_threshold[n] - эта настройка передает компилятору целое число n в диапазоне от 0 до 100. n является оценкой эффективности распараллеливания циклов в процентах. Эту оценку компилятор производит самостоятельно.
Настройки компиляторов Intel для распараллеливания программ с использованием OpenMP
В предыдущем параграфе были рассмотрены возможности автоматического распараллеливания программ для параллельных вычислительных систем с общей памятью. Однако, как правило, в автоматическом режиме нельзя выбрать все имеющиеся возможности для эффективного распараллеливания программ. Поэтому для параллельных вычислительных систем с общей памятью используют средства OpenMP для более глубокого распараллеливания программ.
Современные компиляторы Intel содержат следующие специальные настройки для создания параллельных программ с применением средств OpenMP для параллельных вычислительных систем с общей памятью:
- -openmp - эта настройка позволяет компилятору автоматически создавать многопоточные версии программ с использованием директив OpenMP;
- -openmp_profile - эта настройка добавляет в создаваемую программу средства профилирования программы для последующего анализа с помощью программы VTune Performance Analyzer;
- -openmp_stubs - эта настройка позволяет компилировать OpenMP программы в последовательном режиме. При этом предложения OpenMP игнорируются, а библиотека OpenMP используется редактором связей в последовательном режиме;
- -openmp_report{0|1|2} - эта настройка позволяет создавать отчеты различного уровня - 0, 1 или 2 (наиболее подробный отчет имеет уровень 2) по результатам автоматического распараллеливания с использованием OpenMP. Рекомендуется тщательно анализировать такие отчеты, чтобы четко понять, какие еще места программы могли бы быть распараллелены и почему это не было сделано. Возможно, компилятору не хватило информации для принятия решения о распараллеливании того или иного участка программы. В этом случае это можно сделать вручную.
Итак, вышеперечисленные настройки компиляторов позволяют создавать параллельные версии программ как просто с многопоточным распараллеливанием циклов, так и с помощью директив OpenMP. Возможно также сочетание обоих этих режимов распараллеливания.
В заключение для полноты изложения приведем простейшие команды компиляции программ prog.c и prog.f с помощью компиляторов Intel:
icc -openmp prog.c
и
ifort -openmp prog.f
Здесь prog.c и prog.f - соответственно тексты программ, написанных на алгоритмических языках C/C++ и Fortran с применением директив OpenMP. Для программ, написанных на Fortran, компилятор распознает также расширения файлов с текстами программ for и f90 (для текстов программ, написанных на алгоритмическом языке Fortran 90). В результате компиляции в среде операционной системы Linux создается выполняемый файл a.out. Отметим также, что для создания выполняемых файлов с именем prog следует использовать следующие команды компиляции для программ, написанных на алгоритмических языках C/C++ и Fortran соответственно:
icc -openmp prog.c -o prog
и
ifort -openmp prog.f -o prog
Настройки компиляторов Intel для распараллеливания программ для кластеров с распределенной памятью
В предыдущем параграфе были рассмотрены возможности автоматического распараллеливания программ, эффективные для параллельных вычислительных систем с общей памятью. При создании программ для параллельных вычислительных систем с распределенной памятью, как было отмечено ранее, применяются методы распараллеливания с использованием MPI и PVM. Однако в новой версии компиляторов Intel, начиная с версии 9.1, реализовано расширение OpenMP, предназначенное для распараллеливания программ для вычислительных систем с распределенной памятью. Это расширение известно под названием Cluster OpenMP. В нем имеется возможность объявлять области данных доступными для всех узлов кластера. Эта возможность реализуется с помощью предложения sharable, которое будет рассмотрено далее. Пока же отметим, что это предложение реализует неявную передачу данных между узлами кластера по протоколу Lazy Release Consistency и избавляет программистов от утомительного процесса анализа посылаемых и принимаемых сообщений, необходимого при использовании MPI. В результате процесс параллельного программирования для параллельных вычислительных систем с распределенной памятью существенно упрощается.
Компиляторы Intel, начиная с версии 9.1.x.xx, получили следующие дополнительные настройки, предназначенные для создания параллельных программ для параллельных вычислительных систем с распределенной памятью (кластеров):
- -cluster-openmp - эта настройка позволяет компилятору создавать многопоточные версии программ с использованием директив расширенной версии OpenMP - Cluster OpenMP;
- -cluster-openmp-profile - эта настройка добавляет в создаваемую программу с применением Cluster OpenMP средства профилирования программы для последующего анализа с помощью программы VTune Performance Analyzer;
- -[no-]clomp-sharable-propagation - эта настройка позволяет создать отчет со списком переменных, которые должны быть объявлены программистом общедоступными для всех узлов кластера;
- -[no-]clomp-sharable-info - эта настройка позволяет создать отчет со списком переменных, которые были автоматически объявлены компилятором общедоступными для всех узлов кластера. Далее рассмотрим, как применить эти настройки для создания параллельных программ для вычислительных систем с распределенной памятью.
Во-первых, отметим, что для компиляции программ prog.c и prog.f, написанных соответственно на языках C/C++ и Fortran с использованием Cluster OpenMP, можно воспользоваться соответственно следующими командами:
icc -cluster-openmp prog.c -o prog
и
ifort -cluster-openmp prog.f -o prog
В результате будут созданы выполняемые файлы с именами prog. Однако чтобы запустить программу prog на выполнение с помощью команды
./prog
необходимо, чтобы в директории, откуда запускается программа, содержался файл kmp_cluster.ini. Если же в этой директории этот файл отсутствует, то операционная система ищет файл . kmp_cluster в директории с именем, определенным значением переменной окружения KMP_CLUSTER_PATH. Если же эта переменная окружения отсутствует или не определена, то операционная система ищет . kmp_cluster файл в домашнем каталоге пользователя. В файле kmp_cluster.ini и его аналогах перечисляются узлы кластера, на которых выполняется задание, и количество параллельных потоков на узлах. В следующем примере 7.1 представлена распечатка простейшего kmp_cluster.ini -файла.
[tt1@hpc1 clomp_samples] $ cat kmp_cluster.ini --hostlist = hpc1,hpc2,hpc3,hpc4 --process_threads=2 [tt1@hpc1 clomp_samples]$7.1. Распечатка простейшего kmp_cluster.ini-файла
В этом файле после ключевого слова hostlist следует список узлов кластера, а после ключевого слова process_threads - число физических параллельных потоков в узле (оно равно числу процессоров в узле кластера).
Теперь рассмотрим вопрос использования третьей из вышеперечисленных четырех настроек для перенастройки OpenMP-программ под Cluster OpenMP.
Перед тем как начать перенастройку, следует убедиться, что программа корректно работает под OpenMP. Затем следует оттранслировать и собрать программу с настройкой -cluster-openmp. Если после этого программа будет работать корректно, то можно считать, что перенастройка успешно завершена. В противном случае следует продолжить процесс перенастройки следующим образом.
Во-первых, надо определить переменные программы, которые необходимо сделать общими для всех узлов кластера. Эти общие переменные имеют тип sharable. Для их описания в Cluster OpenMP имеются специальные предложения следующего вида:
#pragma intel omp sharable(var1, var2, ..., varN)
в программах, написанных на языке C/C++, и
!dir$ omp sharable(var1, var2, ..., varN)
в программах, написанных на языке Fortran. Здесь var1, var2, ..., varN - список переменных, которые объявлены общими для всех узлов кластера. В программах на языке Fortran в качестве переменных могут быть использованы имена common-блоков. При этом при описании с помощью предложения Cluster OpenMP sharable имена common-блоков должны быть заключены в слэши, как показано ниже:
!dir$ omp sharable( /cblock1/, /cblock2/, ..., /cblockN/ )
Важно отметить, что переменные, которые применяются в описаниях EQUIVALENCE в программах, написанных на языке Fortran, не могут быть объявлены как sharable.
Для определения sharable -переменных в программе, написанной с OpenMP, можно воспользоваться следующей настройкой компиляторов Intel:
-clomp-sharable-propagation
Эту настройку следует использовать обязательно вместе с настройкой - ipo. В результате компиляции с такой настройкой OMP-программ могут появиться сообщения о необходимости определения sharable -переменных. Пример такого сообщения показан в примере 7.2.
fortcom: Warning: Sharable directive should be inserted by user as '!dir$ omp sharable(s)' in file p2.f, line 2, column 187.2. Пример сообщения о необходимости определения sharable-переменных
Из этого примера видно, что сообщение компилятора указывает конкретное место в программе, где должны быть определены общие для всех узлов кластера переменные, а также Cluster OpenMP-директиву, которую следует использовать для определения имен переменных В программах на языке C++ наряду с предложениями sharable необходимо добавить включение ссылки на файл, в котором описаны переменные sharable. Эта ссылка имеет следующий вид:
#include <kmp_sharable.h>
На втором этапе перенастройки программы под Cluster OpenMP следует в файлах программы расставить необходимые директивы для определения общих для всех узлов кластера переменных, после чего необходимо перекомпилировать и пересобрать программу и убедиться в ее корректной работе.
Отметим, что предложение sharable - единственное новое дополнительное предложение, отличающее Cluster OpenMP от стандартного OpenMP. Однако в Cluster OpenMP имеется значительное число дополнительных специфических настроек, таких, как kmp_cluster.ini -файл и т. п., которые и рассмотрим далее. Начнем с более подробного изучения настроек в kmp_cluster.ini -файле.