Введение

Открытый стандарт для параллелизации OpenMP (Open Multi Processing) — это интерфейс прикладного программирования (API), который поддерживает многоплатформенное программирование с использованием общей памяти в C, C++ и Fortran на различных платформах, архитектурах наборов команд и операционных системах, включая Solaris, AIX, FreeBSD, HP UX, Linux, macOS и Windows. Он состоит из набора директив компилятора, библиотечных функций и переменных окружения, влияющих на поведение во время выполнения. OpenMP управляется некоммерческим технологическим консорциумом OpenMP Architecture Review Board (или OpenMP ARB), совместно определяемым широким кругом ведущих производителей компьютерного оборудования и программного обеспечения, включая Arm, AMD, IBM, Intel, Cray, HP, Fujitsu, Nvidia, NEC, Red Hat, Texas Instruments и Oracle Corporation, для преобразования OpenMP в MPI и расширения OpenMP для систем без общей памяти.

Дизайн

OpenMP — это реализация многопоточности, метода параллелизации, при котором основной поток (последовательность последовательно выполняемых инструкций) порождает заданное количество дочерних потоков, а система распределяет задачу между ними. Затем потоки выполняются одновременно, при этом среда выполнения назначает потоки различным процессорам. Участок кода, предназначенный для параллельного выполнения, соответствующим образом помечается директивой компилятора, которая приводит к формированию потоков перед выполнением этого участка. Версия 3.0 была выпущена в мае 2008 года. Новые возможности версии 3.0 включают концепцию задач и конструкцию задач, что значительно расширяет область применения OpenMP за пределы конструкций параллельного цикла, которые составляли основу OpenMP 2.0. Версия 4.0 спецификации была выпущена в июле 2013 года. Она добавляет или улучшает следующие функции: поддержка ускорителей; атомарные операции; обработка ошибок; привязка потоков к ядрам; расширения для работы с задачами; пользовательское приведение; поддержка SIMD; поддержка Fortran 2003. Текущая версия — 5.2, выпущенная в ноябре 2021 года. Версия 6.0 запланирована к выпуску в 2024 году. Следует отметить, что не все компиляторы (и операционные системы) поддерживают полный набор функций для последних версий.

Основные элементы

Основными элементами OpenMP являются конструкции для создания потоков, распределения рабочей нагрузки, управления данными, синхронизации потоков, процедур времени выполнения на уровне пользователя и переменных окружения. В C/C++ OpenMP использует #прагмы. Специфические прагмы OpenMP перечислены ниже.

Экологические переменные

Метод изменения характеристик выполнения приложений OpenMP. Используется для управления планированием итераций циклов, количеством потоков по умолчанию и другими параметрами. Например, OMP NUM THREADS используется для задания количества потоков для приложения.

Ожидания по результатам

Можно ожидать, что при использовании OpenMP на платформе с N процессорами, скорость выполнения программы возрастет в N раз. Однако, это случается редко по следующим причинам: когда существует зависимость между задачами, процесс должен ждать, пока не будут вычислены данные, необходимые для его работы. Если несколько процессов совместно используют непараллельный ресурс (например, файл для записи), их запросы выполняются последовательно, и каждая нить должна ждать, пока другая нить освободит этот ресурс. Значительная часть программы может быть не поддаваться параллелизации с помощью OpenMP, что ограничивает теоретический предел ускорения законом Амдаля. N процессоров в симметричной мультипроцессорной системе (SMP) могут обладать N-кратной вычислительной мощностью, но пропускная способность памяти обычно не масштабируется линейно. Зачастую, все процессоры используют общий канал памяти, что приводит к снижению производительности из-за конкуренции за пропускную способность. К OpenMP применимы и многие другие распространенные проблемы, влияющие на итоговое ускорение в параллельных вычислениях, такие как балансировка нагрузки и накладные расходы на синхронизацию. Оптимизация компилятора может оказаться менее эффективной при использовании OpenMP, что часто приводит к тому, что однопоточная программа, скомпилированная с OpenMP, работает медленнее, чем тот же код, скомпилированный без флага OpenMP (который будет выполняться последовательно).

Сродство нитей

Некоторые производители рекомендуют задавать аффинность процессора для OpenMP-потоков, чтобы привязать их к конкретным ядрам процессора. Это минимизирует миграцию потоков и стоимость переключения контекста между ядрами, а также повышает локальность данных и снижает трафик, связанный с когерентностью кэша между ядрами (или процессорами).