Форма поиска

 

Библиотеки. OpenMP

Флаги компилятора для включения параллельного режима OpenMP:

Intel -qopenmp
GCC -fopenmp
PGI -mp

 

Содержание

Введение

Прикладной программный интерфейс OpenMP (API OpenMP) предоставляет средства для разработки переносимых масштабируемых параллельных программ для систем с общей памятью. Первая спецификация 1.0 была выпущена в 1997 году для языка Фортран и значительно обновлена в спецификации 1.1 в 1999 году. В 1998 г. была выпущена спецификация для языка Си. Текущая версия стандарта - версия 2.5 выпущена в 2005 году. В этой версии объединена поддержка языков Фортран (77 и 90) и С/C++. До этой версии отдельно выпускались интерфейсы для Фортрана и для Си. Разработкой стандарта занимается организация OpenMP ARB. В настоящее время для открытого обсуждения опубликована версия стандарта 3.0, однако не все компиляторы поддерживают ее в полном объеме. Поддержка OpenMP включена во многие коммерческие компиляторы (Intel, SUN, Portland Group) и, начиная с версии 4.1, поддерживается в наборе открытых компиляторов GNU Linux. По своей сути OpenMP является высокоуровневой надстройкой над Pthread, призванной облегчить разработку многопоточных приложений. OpenMP реализует идею "инкрементального распараллеливания", когда для многопроцессорной системы не пишется специальная параллельная программа, а в обычную последовательную программу добавляются распараллеливающие OpenMP директивы, которые игнорируются обычным компилятором. На примере вычисления числа Pi; покажем, как преобразуется последовательная программа на Фортране в параллельную версию этой программы. Для этого перепишем сначала последовательную программу на язык Фортран.

Параллельная версия программы, разработанная с использованием средств OpenMP, будет иметь вид:

 
Основные директивы OpenMP
Как видно из листинга программы pi_omp.f, не потребовалось ни какой переделки самой программы. Для распараллеливания этой программы в нее всего лишь добавлены строки, содержащие OpenMP директивы. Каждая OpenMP директива начинается с комбинации символов "!$OMP", за которой следует собственно директива, и, возможно, дополнительные ключи. Например, директивы "!$OMP PARALLEL" и "!$OMP END PARALLEL" выделяют параллельную область программы, и весь код, находящийся внутри этого блока, будет выполняться всеми нитями. При входе в эту область в дополнение к основной нити будет порождено N-1 дополнительных нитей. Общее число нитей определяется переменной окружения OMP_NUM_THREADS. Создание параллельной области само по себе не приводит к разделению работы между нитями. Это делается специальными директивами "!$OMP DO" и "!$OMP END DO", которые определяют циклы, которые должны быть выполнены параллельно.
 
В пределах параллельной области данные могут быть или приватными для каждой нити, или общими для всех нитей. По умолчанию, все статические переменные являются общими (исключение составляет переменная параллельного цикла, которая всегда является приватной). Напротив, все динамические переменные по умолчанию являются приватными. В нашем примере не желательно, чтобы общей была переменная x, поэтому используется директива ''!$OMP PARALLEL PRIVATE (x)'', чтобы сделать ее приватной.
 
В программах на языках C/C++ вместо спецкомментариев используются директивы компилятора "#pragma omp". Распараллеливание применяется к for-циклам, для этого используется директива "#pragma omp for". В параллельных циклах запрещается использовать оператор break. Типы и функции OpenMP определены во включаемом файле <omp.h>. При компиляции OpenMP программы компилятор автоматически переведет OpenMP программу в многопотоковую программу с вызовами функций из библиотеки Pthread. Приведем пример OpenMP программы на языке Си.

Пример 1 - компиляция программы pi_omp.c при помощи Intel компилятора

$ source /usr/local/ipsxece/ipsxece_2018_u3/bin/compilervars.sh intel64
$
$ OMP_TEST_PATH=/usr/local/hpc/testfiles/openmp/
$
$ icc $OMP_TEST_PATH/pi_omp.c -qopenmp
$
$ ./a.out 1000
pi=3.141592736923126
eps=8.333333e-08
num threads = 1
$
$ export OMP_NUM_THREADS=10
$
$ ./a.out 1000
pi=3.141592736923126
eps=8.333333e-08
num threads = 10
$
$ export OMP_NUM_THREADS=14
$
$ ./a.out 1000
pi=3.141592736923126
eps=8.333333e-08
num threads = 14
$
$ unset OMP_NUM_THREADS
$
$ ./a.out 1000
pi=3.141592736923126
eps=8.333333e-08
num threads = 1
$

Цикл полезных заметок:

 
Классические учебники: