OpenMP (технология программирования)
OpenMP, наиболее распространённая технология программирования для параллельных вычислительных систем с общей памятью. За основу берётся последовательная программа на традиционном языке программирования, а для создания её параллельной версии пользователю предоставляется набор директив, процедур и переменных окружения. Предполагается, что создаваемая параллельная программа будет переносимой между различными компьютерами с разделяемой памятью, поддерживающими интерфейс OpenMP API.
Разработкой стандарта занимается некоммерческая организация OpenMP ARB (от англ. Architecture Review Board), в которую вошли представители крупнейших компаний – разработчиков SMP-архитектур и программного обеспечения. OpenMP поддерживает работу с языками Fortran и C/C++. Первая спецификация для языка Fortran появилась в октябре 1997 г., а спецификация для языка C/C++ – в октябре 1998 г. Ныне последняя официальная спецификация стандарта – OpenMP 5.2 (принята в ноябре 2021).
В OpenMP используется терминология и модель программирования, близкая к POSIX-интерфейсу для организации нитей Pthreads, например динамически порождаемые нити, общие и разделяемые данные, механизм «замков» для синхронизации. Согласно терминологии POSIX, любой UNIX-процесс состоит из нескольких нитей управления, которые имеют общее адресное пространство, но разные потоки команд и раздельные стеки. В простейшем случае процесс состоит из одной нити. Нити иногда называют также потоками, или легковесными процессами (англ. Light-Weight Processes, LWP).
Технология OpenMP в значительной степени нацелена на то, чтобы пользователь имел один вариант программы для параллельного и последовательного выполнения. Однако в некоторых случаях пользователь может получить программы, которые работают корректно только в параллельном режиме или дают в последовательном режиме другой результат. Более того, из-за накопления ошибок округления результат вычислений с использованием различного количества нитей может в некоторых случаях различаться.
Важным достоинством технологии OpenMP является возможность реализации инкрементального программирования, когда программист постепенно находит участки в программе, содержащие ресурс параллелизма, далее с помощью предоставляемых механизмов делает их параллельными, а затем переходит к анализу следующих участков. Таким образом, в программе нераспараллеленная часть постепенно становится всё меньше. Такой подход значительно облегчает процесс адаптации последовательных программ к параллельным компьютерам, а также их отладку и оптимизацию.
Для использования механизмов OpenMP нужно скомпилировать программу компилятором, поддерживающим OpenMP, с указанием соответствующего ключа (например, в Intel Fortran/C++ используется ключ компилятора – openmp, в GNU Compiler Collection – fopenmp, в Oracle Solaris Studio – xopenmp, в Visual C++ – /openmp, в PGI Compilers – mp). Компилятор интерпретирует директивы OpenMP и создаёт параллельный машинный код. При использовании компиляторов, не поддерживающих OpenMP, директивы OpenMP игнорируются, возможно, с выдачей соответствующих предупреждений.
Распараллеливание в OpenMP выполняется явно при помощи вставки в текст программы специальных директив, а также вызова вспомогательных процедур. При использовании OpenMP предполагается модель SPMD (от англ. Single Program Multiple Data; одна программа – множество данных) параллельного программирования, в рамках которой для всех параллельных нитей используется один и тот же код.
Программа начинается с последовательной области – сначала работает один процесс (нить), при входе в параллельную область порождается ещё некоторое число нитей, между которыми в дальнейшем распределяются части кода. По завершении параллельной области все нити, кроме одной (нити-мастера), завершаются, и начинается последовательная область. В программе может быть любое количество параллельных и последовательных областей. Кроме того, параллельные области могут быть также вложенными друг в друга. В отличие от полноценных процессов, порождение нитей является относительно быстрой операцией, поэтому частые порождения и завершения нитей не так сильно влияют на время выполнения программы.
Для написания эффективной параллельной программы необходимо, чтобы все нити, участвующие в обработке программы, были равномерно загружены полезной работой. Это достигается тщательной балансировкой загрузки, для чего предназначены различные механизмы OpenMP.
Существенна также необходимость синхронизации доступа к общим данным. Само наличие данных, общих для нескольких нитей, приводит к конфликтам при одновременном несогласованном доступе. Поэтому значительная часть функциональности OpenMP предназначена для осуществления различного рода синхронизаций работающих нитей.
OpenMP не выполняет синхронизацию доступа различных нитей к одним и тем же файлам. Если это необходимо для корректности программы, пользователь должен использовать директивы синхронизации или соответствующие библиотечные процедуры. При доступе каждой нити к своему файлу никакая синхронизация не требуется.
Для написания эффективной параллельной программы c использованием технологии OpenMP необходимо: найти в программе ресурс параллелизма, распределить операции по исполнительным устройствам, разграничить доступ к данным в общей памяти.