Презентацию к данной лекции Вы можете скачать здесь.
При создании процесса порождается главный поток, выполняющий инициализацию процесса. Он же начинает выполнение команд.
Поток и процесс соотносятся следующим образом:
Конкуренция за ресурсы (видимый параллелизм)
Реальный параллелизм
Для реализации реального параллелизма требуется соответствующая архитектура – многоядерная или многопроцессорная с общей памятью.
При разработке многопоточных приложений возникают следующие проблемы:
Гонки за данными являются следствием зависимостей, когда несколько потоков модифицируют содержимое одной и той же области памяти. Наличие гонок за данными не всегда является очевидным. Они могут приводить к конфликтам двух типов:
Блокировка (тупик) возникает, если поток ожидает выполнение условия, которое не может быть выполнено. Обычно возникновение тупиковой ситуации является следствием конкуренции потоков за ресурс, который удерживается одним из них.
Число программных потоков должно совпадать с числом аппаратных потоков
| POSIX Threads Windows API | низкоуровневые инструменты |
| OpenMP | высокоуровневые инструменты |
Прагмы, имена функций и переменных окружения OpenMP начинаются с omp, omp_ или OMP_
Формат директивы:
#pragma omp директива [оператор_1[, оператор_2, …]]
Заголовочный файл omp.h.
Директивы компилятора, имена подпрограмм и переменных окружения начинаются с OMP или OMP_.
Формат директивы компилятора:
{!|C|*}$OMP директива [оператор_1[, оператор_2, …]]
Директива начинается в первой (фиксированный формат записи текста) или произвольной (свободный формат) позиции строки. Допускается продолжение директивы в следующей строке, в этом случае действует стандартное для данной версии языка правило для обозначения строки продолжения (непробельный символ в шестой позиции для фиксированного формата записи и амперсанд для свободного формата).
parallel … end parallel
Границы параллельной секции программы.С данной директивой могут использоваться следующие операции:
private; shared; default; firstprivate; reduction; if; copyin; num_threads
#pragma omp for цикл for
Границы цикла, исполняемого в параллельном режиме.С данной директивой могут использоваться следующие операции:
private; firstprivate; lastprivate; reduction; schedule; ordered; nowait.
sections … end sections
Вложенные секции программы, задаваемые директивами section, распределяются между нитями. С данной директивой могут использоваться следующие операции:
private; firstprivate; lastprivate; reduction; nowait.
section
Определяет часть sections, которая выполняется одной нитью.
parallel do цикл do end parallel do
Объединяет директивы parallel и do.
parallel sections … end parallel sections
Объединяет директивы parallel и sections.
critical[(блокировка)] … end critical[(блокировка)]
Обрамляет блок программы, доступ к которому в любой момент времени может получить только одна нить (критическая секция). Блокировка – необязательное имя критической секции.
barrier
Барьерная синхронизация нитей.
atomic
Объявляет операцию атомарной (то есть, одновременный доступ по записи разных нитей запрещен). Применяется только к оператору, непосредственно следующему после данной директивы. Он может иметь следующий вид:
x = x {+|-|*|/|.AND.|.OR.|.EQV.|.NEQV.}
скалярное_выражение_не_содержащее_x
x = скалярное_выражение_не_содержащее_x
{+|-|*|/|.AND.|.OR.|.EQV.|.NEQV.}
x = {MAX|MIN|IAND|IOR|IEOR}
(x, скалярное_выражение_не_содержащее_x)
x = {MAX|MIN|IAND|IOR|IEOR}
(скалярное_выражение_не_содержащее_x, x)
flush[(список переменных)]
Задает точку синхронизации, в которой значения переменных, указанных в списке и видимых из данной нити, записываются в память. Этим обеспечивается согласование содержимого памяти, доступного разным нитям.
ordered … end ordered
Сохранение того порядка выполнения итераций цикла, который соответствует последовательному выполнению программы.
private(список переменных)
Объявляет переменные из списка локальными.
firstprivate(список переменных)
Объявляет переменные из списка локальными и инициализирует их значениями из блока программы, предшествующего данной директиве.
lastprivate(список переменных)
Объявляет переменные из списка локальными и назначает им значения из того блока программы, который был выполнен последним.
nowait
Отменяет барьерную синхронизацию при завершении выполнения параллельной секции.
shared(список переменных)
Объявляет переменные из списка глобальными.
reduction(операция|встроенная функция: список переменных)
Приведение значений локальных переменных из списка с помощью указанной операции или встроенной функции языка.
schedule(характер_распределения_итераций[, количество_итераций_цикла])
Характер распределения итераций цикла между нитями:
static – количество итераций цикла, передаваемых для выполнения каждой нити
фиксировано и распределяется между нитями по принципу кругового планирования.
Если количество итераций не указано, оно полагается равным 1;
dynamic – количество итераций цикла, передаваемых для выполнения каждой нити
фиксировано. Очередная "порция" итераций передается освободившейся нити;
guided – количество итераций цикла, передаваемых для выполнения каждой нити
уменьшается. Очередная "порция" итераций передается освободившейся нити;
runtime – тип распределения работы определяется во время выполнения программы,
например, с помощью переменной окружения OMP_SCHEDULE.
void omp_set_num_threads(int threads); subroutine omp_set_num_threads(threads) integer threads
Задает количество потоков (threads) при выполнении параллельных секций программы
int omp_get_num_threads(void); integer function omp_get_num_threads()
Возвращает количество потоков, используемых для выполнения параллельной секции.
void omp_set_nested(int nested); subroutine omp_set_nested(nested) integer nested
Разрешает или запрещает вложенный параллелизм. По умолчанию запрещен.
int omp_get_nested(void); logical function omp_get_nested()
Определяет, разрешен ли вложенный параллелизм.
void omp_init_lock(omp_lock_t *lock); subroutine omp_init_lock(lock) integer(kind = omp_lock_kind) :: lock
Инициализирует блокировку, связанную с идентификатором lock, для использования в последующих вызовах.
void omp_set_lock(omp_lock_t *lock); subroutine omp_set_lock(lock) integer(kind = omp_lock_kind) :: lock
Переводит потоки из состояния выполнения в состояние ожидания до тех пор, пока блокировка, связанная с идентификатором lock, не окажется доступной. Поток становится владельцем доступной блокировки.
void omp_unset_lock(omp_lock_t *lock); subroutine omp_unset_lock(lock) integer(kind = omp_lock_kind) :: lock
После выполнения вызова поток перестает быть владельцем блокировки, связанной с идентификатором lock. Если поток не был владельцем блокировки, результат вызова не определен.
double omp_get_wtime(void); double precision function omp_get_wtime()
Время в секундах, прошедшее с произвольного момента в прошлом. Точка отсчета остается неизменной в течение всего времени выполнения программы
double omp_get_wtick(void); double precision function omp_get_wtick()
Время в секундах, прошедшее между последовательными "тиками". Это время является мерой точности таймера.
Переменные окружения задаются следующим образом:
export ПЕРЕМЕННАЯ=значение (UNIX) set ПЕРЕМЕННАЯ=значение (Microsoft Windows)
OMP_NUM_THREADS
Задает количество нитей при выполнении параллельных секций программы.
OMP_SCHEDULE
Задает способ распределения итераций циклов между нитями. Возможные значения:
static; dynamic; guided.
Количество итераций (необязательный параметр) указывается после одного из этих ключевых слов, отделяясь от него запятой, например:
export OMP_SCHEDULE="static, 10"
program omp_example integer i, k, N real*4 sum, h, x print *, "Please, type in N:" read *, N h = 1.0 / N sum = 0.0 !$OMP PARALLEL DO SCHEDULE(STATIC) REDUCTION(+:sum) do i = 1, N x = i * h sum = sum + 1.e0 * h / (1.e0 + x**2) enddo print *, 4.0 * sum end
#include "omp.h"
#include <stdio.h >
double f(double x) {
return 4.0 / (1 + x * x); }
main () {
const long N = 100000;
long i;
double h, sum, x;
sum = 0;
h = 1.0 / N;
#pragma omp parallel shared(h) {
#pragma omp for private(x) reduction(+:sum)
for (i = 0; i < N; i++) {
x = h * (i + 0.5);
sum = sum + f(x); } }
printf("PI = %f\n", sum / N); }
OpenMP поддерживается компиляторами Intel®, GCC и другими.
Компиляция OpenMP-программ выполняется с ключом -openmp или –fopenmp.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.