Введение
Открытый стандарт для параллелизации 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 (Open Multi Processing) is an application programming interface (API) that supports multi platform shared memory multiprocessing programming in C, C++, and Fortran, on many platforms, instruction set architectures and operating systems, including Solaris, AIX, FreeBSD, HP UX, Linux, macOS, and Windows. It consists of a set of compiler directives, library routines, and environment variables that influence run time behavior. OpenMP is managed by the nonprofit technology consortium OpenMP Architecture Review Board (or OpenMP ARB), jointly defined by a broad swath of leading computer hardware and software vendors, including Arm, AMD, IBM, Intel, Cray, HP, Fujitsu, Nvidia, NEC, Red Hat, Texas Instruments, and Oracle Corporation. to translate OpenMP into MPI
and to extend OpenMP for non shared memory systems.
Дизайн
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 (который будет выполняться последовательно).
When a dependency exists, a process must wait until the data it depends on is computed. When multiple processes share a non parallel proof resource (like a file to write in), their requests are executed sequentially. Therefore, each thread must wait until the other thread releases the resource. A large part of the program may not be parallelized by OpenMP, which means that the theoretical upper limit of speedup is limited according to Amdahl's law. N processors in a symmetric multiprocessing (SMP) may have N times the computation power, but the memory bandwidth usually does not scale up N times. Quite often, the original memory path is shared by multiple processors and performance degradation may be observed when they compete for the shared memory bandwidth. Many other common problems affecting the final speedup in parallel computing also apply to OpenMP, like load balancing and synchronization overhead. Compiler optimisation may not be as effective when invoking OpenMP. This can commonly lead to a single threaded OpenMP program running slower than the same code compiled without an OpenMP flag (which will be fully serial).
Сродство нитей
Некоторые производители рекомендуют задавать аффинность процессора для OpenMP-потоков, чтобы привязать их к конкретным ядрам процессора. Это минимизирует миграцию потоков и стоимость переключения контекста между ядрами, а также повышает локальность данных и снижает трафик, связанный с когерентностью кэша между ядрами (или процессорами).