[МУЗЫКА] [МУЗЫКА] [МУЗЫКА] Здравствуйте, уважаемые слушатели! В этой лекции мы рассмотрим особенности технологии параллельного программирования OpenMP и её основные компоненты. В настоящее время наиболее популярной технологией параллельного программирования для систем с общей памятью стала технология OpenMP. И это связано с тем, что она основана на традиционных языках программирования, а пользователю предоставляет дополнительные компоненты, которые позволяют создавать параллельные программы. Разработкой стандарта занимается некоммерческая организация OPENMP ARB, в которую вошли представители крупнейших компаний-разработчиков SMP архитектур и программного обеспечения. Это такие крупные компании как Intel, AMD, NVIDIA, IBM и другие крупные компании. OpenMP поддерживает работу с языками FORTRAN и С или С++. На данный момент последняя официальная спецификация данного стандарта — это OpenMP 4.0. Принята данная спецификация в июле 2013 года. Позже еще выходили небольшие дополнения к данной спецификации, но они явились несущественными уже. Интерфейс OpenMP задуман как стандарт для программирования на масштабируемых SMP системах в модели общей памяти. Давайте разберёмся, как происходит распараллеливание вычислений в OpenMP. OpenMP реализует параллельное вычисление с помощью многопоточности. Данный подход мы с Вами рассматривали на прошлой лекции и подробно его обсуждали. В OpenMP используется модель параллельного выполнения «ветвление-слияние» или fork-join parallelism. Программа начинает выполнение в одном потоке, называемым главным, или мастер-потоком. Главный поток выполняет все последовательные участки кода. Когда поток достигает директивы, которая создаёт параллельную область, он порождает дополнительные потоки. Все эти потоки исполняют код структурной области, связанной с директивой, создающей эту параллельную область. В конце параллельной области дополнительные потоки удаляются. И у нас остаётся только один мастер-поток, он и продолжает выполнение после завершения этой параллельной области. Предполагается, что потоки выполняются сразу на нескольких процессорах или ядрах. Процессоров и ядер может быть меньше, чем мы создали в параллельной области. К тому же параллельные области могут быть вложенными друг в друга. Создание процесса намного дороже, чем создание отдельного потока или нескольких потоков, поэтому это не так сильно влияет на время выполнения программы. В стандарт OpenMP входят спецификации набора: директив для компилятора, вспомогательных функций и переменные среды окружения. Давайте рассмотрим каждый компонент более подробно. Значительная часть функциональности OpenMP реализуется при помощи директив компилятора. Все директивы OpenMP можно разделить на три категории. Это определение параллельной области, распределение работы и директивы, связанные с синхронизацией. В эти категории входят различные директивы, и большую часть из них мы с вами разберём на следующих лекциях. Разберём, как они работают и особенности их применения. А сейчас рассмотрим только общий синтаксис директив. Его вы можете видеть на экране. Директивы OpenMP в программах на языке С оформляются указаниями при процессах. Эти указания начинаются с служебных слов #pragma omp. Ключевое слово «omp» используется для того, чтобы исключить случайное совпадение имён директив с другими именами. Объектом действия каждой директивы может являться либо один оператор, либо целый блок операторов, которые следуют за данной директивой. В OpenMP такие операторы или блоки называются ассоциированными с директивой. Каждая директива может иметь несколько дополнительных атрибутов или опций. Отдельно специфицируются опции для назначения классов переменных, которые могут быть атрибутами различных директив, и мы их также будем отдельно рассматривать. Порядок опций в описании директивы на самом деле несущественен. Вы можете их вставить в различном порядке, более того, они могут на самом деле встречаться и несколько раз. После некоторых опций может следовать список переменных. И эти переменные между собой разделяются запятой. Например, в данной директиве parallel мы использовали опцию private, а в скобках через запятую указали имена переменных. Теперь давайте рассмотрим следующий пункт — это функции. Чтобы задействовать функции в библиотеке OpenMP, в программу нужно включить заголовочный файл omp.h. Если Вы используете в приложении только директивы, в принципе, этот файл включать необязательно. Все функции, используемые в OpenMP, начинаются с префикса omp_. И если пользователь, то есть вы, не будете в программу включать функции с таким префиксом, то никаких конфликтов между объектами OpenMP и вашими функциями заведомо не будет. Например, в библиотеке имеется функция, которая позволяет определить номер текущего потока в параллельной области. Это функция omp_get _thread_num. И третий компонент, который включает в себя технология OpenMP — это переменное окружение. Задавать вы их можете через командную строку, и задание этих переменных окружений влияет на выполнение программы. Например, переменное окружение OMP_NUM_THREADS позволяет задать количество потоков, которые будут выполнять параллельную область. В Windows значение этих переменных можно установить с использованием команды set, а в Linux в встроенной командной оболочке Bash можно задать их с использованием команды export. Примеры вы видите на экране. Теперь давайте ответим на такой вопрос: как написать параллельную программу? Распараллеливание в OpenMP выполняется явно при помощи вставки в текст программы специальных директив, а также вызова вспомогательных функций. При использовании OpenMP предполагается SMPD-модель (то есть это Single Program Multiple Data) параллельного программирования, в рамках которой для всех параллельных потоков используется один и тот же код. За основу, как правило, берется последовательная программа, которая у Вас уже имеется. Допустим, у нас есть обычная программа сложения двух векторов. Если мы её запустим, то её выполнять будет только одно ядро нашего процессора или один процессор, а остальные ядра или процессоры будут прохлаждаться и отдыхать, ничего не делая. Мы хотим ускорить вычисления и задействовать все ядра процессора или все процессоры, имеющиеся у нас, чтобы достичь максимальной эффективности использования всех вычислительных ресурсов. С использованием OpenMP нам достаточно добавить две директивы в нашу программу. Это перед первым циклом и перед вторым циклом, а далее скомпилировать нашу программу с использованием компилятора, который поддерживает технологию OpenMP. И в результате у нас получится параллельная программа. Технология OpenMP направлена на то, чтобы у пользователя была одна версия программы, как последовательная, так и параллельная. Но вы можете изначально писать свою программу как параллельную, используя соответствующие алгоритмы, методы и технологии. Но нужно всегда помнить, что при выполнении программы и при выполнении вычислений существует ошибка округления. Ей свойственно накапливаться, поэтому результаты вычисления по программе иногда могут отличаться в зависимости от того, сколько потоков выполняют вашу программу. В начале лекции я говорил о том, что последняя версия спецификации — это 4.0. Я хотел бы, чтобы вы поискали и выяснили для себя, какие новые возможности предоставляет данная спецификация, и как вы думаете, какие из этих нововведений будут вам в дальнейшем полезны. А на следующей лекции я расскажу, что мне кажется наиболее полезным из последних нововведений. До новых встреч!