Параллельное программирование с использованием OpenMP. Антонов (2009) (Параллельное программирование с использованием OpenMP. Антонов (2009).pdf), страница 3
Описание файла
PDF-файл из архива "Параллельное программирование с использованием OpenMP. Антонов (2009).pdf", который расположен в категории "". Всё это находится в предмете "суперкомпьютерное моделирование и технологии" из 11 семестр (3 семестр магистратуры), которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 3 страницы из PDF
Таймеры разных нитеймогут быть не синхронизированы и выдавать различные значения.Функция omp_get_wtick() возвращает в вызвавшей нити разрешение таймера в секундах. Это время можно рассматривать как меру точности таймера.Си:double omp_get_wtick(void);Фортран:double precision function omp_get_wtick()Примериллюстрирует применение функций omp_get_wtime() иomp_get_wtick() для работы с таймерами в OpenMP. В данном примерепроизводится замер начального времени, затем сразу замер конечного времени. Разность времён даёт время на замер времени. Кроме того, измеряетсяточность системного таймера.2#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){double start_time, end_time, tick;start_time = omp_get_wtime();end_time = omp_get_wtime();tick = omp_get_wtick();printf("Время на замер времени %lf\n", end_time-start_time);printf("Точность таймера %lf\n", tick);}Пример 2a.
Работа с системными таймерами на языке Си.program example2binclude "omp_lib.h"double precision start_time, end_time, tickstart_time = omp_get_wtime()end_time = omp_get_wtime()tick = omp_get_wtick()print *, "Время на замер времени ", end_time-start_timeprint *, "Точность таймера ", tickendПример 2b. Работа с системными таймерами на языке Фортран.Задания• Определите, какую версию стандарта OpenMP поддерживает компилятор на доступной системе.• Откомпилируйте любую последовательную программу с включениемопций поддержки технологии OpenMP и запустите с использованием12нескольких нитей. Сколько нитей будет реально исполнять операторыданной программы?• Может ли программа на OpenMP состоять только из параллельных областей? Только из последовательных областей?• Чем отличается нить-мастер от всех остальных нитей?• При помощи функций OpenMP попробуйте определить время, необходимое для работы функции omp_get_wtick().
Хватает ли для этоготочности системного таймера?13Параллельные и последовательные областиВ момент запуска программы порождается единственная нить-мастер или«основная» нить, которая начинает выполнение программы с первого оператора. Основная нить и только она исполняет все последовательные областипрограммы. При входе в параллельную область порождаются дополнительные нити.Директива parallelПараллельная область задаётся при помощи директивы parallel (parallel... end parallel).Си:#pragma omp parallel [опция[[,] опция]...]Фортран:!$omp parallel [опция[[,] опция]...]<код параллельной области>!$omp end parallelВозможные опции:• if(условие) – выполнение параллельной области по условию.
Вхождение в параллельную область осуществляется только при выполнениинекоторого условия. Если условие не выполнено, то директива не срабатывает и продолжается обработка программы в прежнем режиме;• num_threads (целочисленное выражение) – явное задание количества нитей, которые будут выполнять параллельную область; по умолчанию выбирается последнее значение, установленное с помощью функцииomp_set_num_threads(),илизначениепеременнойOMP_NUM_THREADS;• default(private|firstprivate|shared|none) – всем переменным впараллельной области, которым явно не назначен класс, будет назначенкласс private, firstprivate или shared соответственно; none означает, что всем переменным в параллельной области класс должен бытьназначен явно; в языке Си задаются только варианты shared или none;• private(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; начальное значение локальныхкопий переменных из списка не определено;14• firstprivate(список) – задаёт список переменных, для которых порождается локальная копия в каждой нити; локальные копии переменных инициализируются значениями этих переменных в нити-мастере;• shared(список) – задаёт список переменных, общих для всех нитей;• copyin(список) – задаёт список переменных, объявленных какthreadprivate, которые при входе в параллельную область инициализируются значениями соответствующих переменных в нити-мастере;• reduction(оператор:список) – задаёт оператор и список общих переменных; для каждой переменной создаются локальные копии в каждой нити; локальные копии инициализируются соответственно типуоператора (для аддитивных операций – 0 или его аналоги, для мультипликативных операций – 1 или её аналоги); над локальными копиямипеременных после выполнения всех операторов параллельной областивыполняется заданный оператор; оператор это: для языка Си – +, *, -,&, |, ^, &&, ||, для языка Фортран – +, *, -, .and., .or., .eqv., .neqv.,max, min, iand, ior, ieor; порядок выполнения операторов не определён, поэтому результат может отличаться от запуска к запуску.При входе в параллельную область порождаются новые OMP_NUM_THREADS-1нитей, каждая нить получает свой уникальный номер, причём порождающаянить получает номер 0 и становится основной нитью группы («мастером»).Остальные нити получают в качестве номера целые числа с 1 доOMP_NUM_THREADS-1.
Количество нитей, выполняющих данную параллельную область, остаётся неизменным до момента выхода из области. При выходе из параллельной области производится неявная синхронизация и уничтожаются все нити, кроме породившей.Все порождённые нити исполняют один и тот же код, соответствующий параллельной области. Предполагается, что в SMP-системе нити будут распределены по различным процессорам (однако это, как правило, находится в ведении операционной системы).Пример 3 демонстрирует использование директивы parallel.
В результатевыполнения нить-мастер напечатает текст "Последовательная область 1",затем по директиве parallel порождаются новые нити, каждая из которыхнапечатает текст "Параллельная область", затем порождённые нити завершаются и оставшаяся нить-мастер напечатает текст "Последовательная область 2".15#include <stdio.h>int main(int argc, char *argv[]){printf("Последовательная область 1\n");#pragma omp parallel{printf("Параллельная область\n");}printf("Последовательная область 2\n");}Пример 3a. Параллельная область на языке Си.program example3bprint *, "Последовательная область 1"!$omp parallelprint *, "Параллельная область"!$omp end parallelprint *, "Последовательная область 2"endПример 3b. Параллельная область на языке Фортран.Пример 4 демонстрирует применение опции reduction.
В данном примерепроизводится подсчет общего количества порождённых нитей. Каждая нитьинициализирует локальную копию переменной count значением 0. Далее,каждая нить увеличивает значение собственной копии переменной count наединицу и выводит полученное число. На выходе из параллельной областипроисходит суммирование значений переменных count по всем нитям, и полученная величина становится новым значением переменной count в последовательной области.#include <stdio.h>int main(int argc, char *argv[]){int count = 0;#pragma omp parallel reduction (+: count){count++;printf("Текущее значение count: %d\n", count);}printf("Число нитей: %d\n", count);}Пример 4a. Опция reduction на языке Си.16program example4binteger countcount=0!$omp parallel reduction (+: count)count=count+1print *, "Текущее значение count: ", count!$omp end parallelprint *, "Число нитей: ", countendПример 4b.
Опция reduction на языке Фортран.Сокращённая записьЕсли внутри параллельной области содержится только один параллельныйцикл, одна конструкция sections или одна конструкция workshare, то можно использовать укороченную запись: parallel for (parallel do для языка Фортран), parallel sections или parallel workshare. При этом допустимо указание всех опций этих директив, за исключением опции nowait.Переменные среды и вспомогательные функцииПеред запуском программы количество нитей, выполняющих параллельнуюобласть, можно задать, определив значение переменной средыOMP_NUM_THREADS.
Например, в Linux в командной оболочке bash это можносделать при помощи следующей команды:export OMP_NUM_THREADS=nЗначение по умолчанию переменной OMP_NUM_THREADS зависит от реализации. Из программы её можно изменить с помощью вызова функцииomp_set_num_threads().Си:void omp_set_num_threads(int num);Фортран:subroutine omp_set_num_threads(num)integer numПример 5 демонстрирует применение функции omp_set_num_threads() иопции num_threads.
Перед первой параллельной областью вызовом функцииomp_set_num_threads(2) выставляется количество нитей, равное 2. Но кпервой параллельной области применяется опция num_threads(3), котораяуказывает, что данную область следует выполнять тремя нитями. Следовательно, сообщение "Параллельная область 1" будет выведено тремя нитями. Ко второй параллельной области опция num_threads не применяется, по17этомудействуетзначение,установленноефункциейomp_set_num_threads(2), и сообщение "Параллельная область 2" будетвыведено двумя нитями.#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){omp_set_num_threads(2);#pragma omp parallel num_threads(3){printf("Параллельная область 1\n");}#pragma omp parallel{printf("Параллельная область 2\n");}}Пример 5a.
Функция omp_set_num_threads() и опция num_threads на языке Си.!$omp!$omp!$omp!$ompprogram example5binclude "omp_lib.h"call omp_set_num_threads(2);parallel num_threads(3)print *, "Параллельная область 1"end parallelparallelprint *, "Параллельная область 2"end parallelendПример 5b. Функция omp_set_num_threads() и опция num_threads на языкеФортран.В некоторых случаях система может динамически изменять количество нитей, используемых для выполнения параллельной области, например, для оптимизации использования ресурсов системы. Это разрешено делать, если переменная среды OMP_DYNAMIC установлена в true. Например, в Linux вкомандной оболочке bash её можно установить при помощи следующей команды:export OMP_DYNAMIC=trueВ системах с динамическим изменением количества нитей значение по умолчанию не определено, иначе значение по умолчанию: false.ПеременнуюOMP_DYNAMIComp_set_dynamic().можноустановить18спомощьюфункцииСи:void omp_set_dynamic(int num);Фортран:subroutine omp_set_dynamic(num)logical numНа языке Си в качестве значения параметра функции omp_set_dynamic() задаётся 0 или 1, а на языке Фортран – .FALSE.
или .TRUE. Если система неподдерживает динамическое изменение количества нитей, то при вызовефункции omp_set_dynamic() значение переменной OMP_DYNAMIC не изменится.Узнать значение переменной OMP_DYNAMIC можно при помощи функцииomp_get_dynamic().Си:int omp_get_dynamic(void);Фортран:logical function omp_get_dynamic()Пример 6 демонстрирует применение функций omp_set_dynamic() иomp_get_dynamic().
Сначала распечатывается значение, полученное функцией omp_get_dynamic() – это позволяет узнать значение переменнойOMP_DYNAMICпоумолчанию.Затемприпомощифункцииomp_set_dynamic() переменная OMP_DYNAMIC устанавливается в true, чтоподтверждает выдача ещё один раз значения функции omp_get_dynamic().Затем порождается параллельная область, выполняемая заданным количеством нитей (128). В параллельной области печатается реальное число выполняющих её нитей.