Openmp visual studio 2017


Переход от OpenMP к среде выполнения с параллелизмом

 

Самая актуальная документация по Visual Studio 2017: Документация по Visual Studio 2017.

Среда выполнения с параллелизмом позволяет использовать самые разные модели программирования. Эти модели могут частично совпадать с моделями других библиотек или дополнять их. В документах в этом разделе OpenMP сравнивается со средой выполнения с параллелизмом. Также даны примеры миграции существующего кода OpenMP для использования среды выполнения с параллелизмом.

Модель программирования OpenMP определяется открытым стандартом и имеет четко определенные привязки к языкам программирования Fortran и C/C++. OpenMP версий 2.0 и 2.5, поддерживаемых компилятором Visual C++, хорошо подходит для использования с параллельными итеративными алгоритмами, т. е. алгоритмами, выполняющими параллельные итерации с массивом данных. OpenMP 3.0 поддерживает не только итеративные, но и неитеративные задачи.

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

Однако OpenMP не так хорошо подходит для использования в менее ограниченных вычислительных средах. Например, при попытке выполнять рекурсивные операции (такие, как алгоритм быстрой сортировки или поиск в дереве данных) с помощью модели OpenMP версий 2.0 или 2.5 могут возникнуть сложности. Среда выполнения с параллелизмом дополняет OpenMP за счет библиотеки асинхронных агентов и библиотеки параллельных шаблонов (PPL). Библиотека асинхронных агентов поддерживает параллелизм недетализированных задач; PPL поддерживает более детализированные параллельные задачи. Среда выполнения с параллелизмом предоставляет инфраструктуру, необходимую для параллельного выполнения операций, чтобы разработчик мог сконцентрироваться на логике приложения. Так как среда выполнения с параллелизмом применяет несколько моделей программирования, дополнительная нагрузка, связанная с планированием, может быть больше, чем для других библиотек с параллелизмом, таких как OpenMP. Поэтому рекомендуется постоянно тестировать производительность по мере преобразования существующего кода OpenMP для использования среды выполнения с параллелизмом.

Выполнить миграцию существующего кода OpenMP для использования среды выполнения с параллелизмом может быть выгодно в следующих случаях.

СлучаиПреимущества среды выполнения с параллелизмом
Необходима расширяемая платформа параллельного программирования.Многие функции среды выполнения с параллелизмом можно расширить. Кроме того, существующие функции можно объединять для создания новых. Так как модель OpenMP основывается на директивах компилятора, ее трудно расширять.
Для приложения выгодно совместное блокирование.Если задача блокируется, так как ей нужен недоступный в настоящий момент ресурс, среда выполнения с параллелизмом может выполнять другие задачи, пока первая задача ожидает ответа.
Для приложения выгодна динамическая балансировка нагрузки.Среда выполнения с параллелизмом использует алгоритм планирования, перераспределяющий вычислительные ресурсы при изменении рабочей нагрузки. Когда планировщик в OpenMP выделяет вычислительные ресурсы параллельной области, это выделение ресурсов не изменяется до окончания вычисления.
Необходима поддержка обработки исключений.PPL позволяет перехватывать исключения как внутри, так и снаружи от параллельной области или цикла. В OpenMP необходимо обрабатывать исключение внутри параллельной области или цикла.
Необходим механизм отмены.PPL позволяет приложениям отменять как отдельные задачи, так и параллельные деревья работы. В OpenMP приложение должно реализовывать собственные механизмы отмены.
Необходимо, чтобы начало и завершение выполнения параллельного кода происходило в разных контекстах.Среда выполнения с параллелизмом позволяет начать задачу в одном контексте, а затем дождаться выполнения или отменить эту задачу в другом контексте. В OpenMP вся параллельная работа должна начинаться и завершаться в одном контексте.
Необходима расширенная поддержка отладки.В Visual Studio входят окна Параллельные стеки и Параллельные задачи, упрощающие отладку многопоточных приложений.

Дополнительные сведения о поддержке отладки в среде выполнения с параллелизмом см. в разделах Использование окна задач, Использование окна "Параллельные стеки" и Пошаговое руководство. Отладка параллельного приложения.

В следующих случаях может быть невыгодно выполнять миграцию существующего кода OpenMP для использования среды выполнения с параллелизмом.

СлучаиОбъяснение
Приложение уже соответствует требованиям.Если вас устраивает производительность и поддержка отладки приложения, миграция может не быть оправдана.
Основные части параллельных циклов выполняют немного работы.Преимущества параллельного выполнения основной части цикла могут не компенсировать затраты на работу планировщика заданий среды выполнения с параллелизмом, особенно если основная часть цикла небольшая.
Приложение написано на C.Так как среда выполнения с параллелизмом использует многие компоненты C++, она может не подходить, если невозможно писать код, позволяющий приложению на C полностью использовать эту среду.

Практическое руководство. Преобразование параллельного цикла for OpenMP для использования среды выполнения с параллелизмомПоказывает, как преобразовать простой цикл, использующий директивы parallel и for OpenMP, для использования алгоритма Concurrency::parallel_for среды выполнения с параллелизмом.

Практическое руководство. Преобразование цикла OpenMP, использующего отмену для использования среды выполнения с параллелизмомПоказывает, как преобразовать цикл OpenMP parallel for, для которого не требуется выполнение всех итераций, для выполнения с использованием механизма отмены среды выполнения с параллелизмом.

Практическое руководство. Преобразование цикла OpenMP, использующего обработку исключений для использования среды выполнения с параллелизмомПоказывает, как преобразовать цикл OpenMP parallel for, выполняющий обработку исключений, для использования механизма обработки исключений среды выполнения с параллелизмом.

Практическое руководство. Преобразование цикла OpenMP, использующего переменную сокращения для использования среды выполнения с параллелизмомПоказывает, как преобразовать для использования среды выполнения с параллелизмом цикл parallel for OpenMP, использующий предложение reduction.

Среда выполнения с параллелизмомOpenMPБиблиотека параллельных шаблоновБиблиотека асинхронных агентов

msdn.microsoft.com

Параллельные заметки №2 – инструментарий для OpenMP / Блог компании Intel / Хабрахабр

Прежде чем приступить к изучению методики распараллеливания программ с помощью технологии OpenMP рассмотрим инструментарий, который нам потребуется. А потребуется нам в первую очередь Visual Studio 2005/2008 и Intel Parallel Studio. Преимущество технологии OpenMP заключается в том, что взяв код последовательной программы, можно распараллелить его без существенной модификации. Это достигается расстановкой специальных директив. Конечно, на практике придется не только вставлять директивы, но и править сам код приложения, но этих изменений будет гораздо меньше, чем если использовать альтернативные технологии, такие как MPI.

Вышесказанное означает, что мы можем взять обыкновенный последовательный код на языке Си/Си++ и начать его постепенно распараллеливать. Для этого нам достаточно включить в проекте поддержку OpenMP. В среде Visual Studio 2005/2008 зайдите в свойства проекта и выберете вкладку C/C++ / Language, как показано на рисунке 1. Рисунок 1 — Вкладка Visual Studio с настройками проекта, где можно включить поддержку OpenMP

Не забудьте также выбрать платформы и конфигурации, в которых вы планируете использовать OpenMP. Как показано на рисунке 2, мы выбрали все конфигурации (debug, release) и все платформы (Win32, x64). Рисунок 2 — Выбор конфигураций и платформ, для которых мы устанавливаем параметры

Поддержка OpenMP включается опцией «OpenMP Support» как показано на рисунке 3. Рисунок 3 — Поддержка OpenMP включена

Следующим шагом является подключение заголовочного файла «omp.h». Часто рационально поместить "#include <omp.h>" в stdafx.h, чтобы он был виден во всем проекте.

Вот и все подготовительные шаги, которые необходимы, чтобы начать осваивать технологию OpenMP и распараллеливать программный код. Знакомство с OpenMP мы начнем со следующей заметки. Сейчас мы продолжим знакомство с инструментами. Дело в том, что хотя возможностей Visual Studio 2005/2008 достаточно чтобы разрабатывать параллельные OpenMP программы, это слишком спартанские условия. Для полноценной работы разумно воспользоваться Intel Parallel Studio. Я не сотрудник Intel и за рекламу инструментов мне никто не платит. Parallel Studio действительно удобный и крайне полезный инструмент для разработки параллельных приложений. Рекомендую на основании собственного опыта.

Дистрибутив Intel Parallel Studio занимает порядка 460 Мбайт и доступен для скачивания с сайта Intel. При этом полная функциональность Parallel Studio будет доступна в течении одного пробного месяца, что вполне достаточно, чтобы познакомиться с принципами работы и поэкспериментировать с параллельным кодом. Parallel Studio интегрируется внутрь Visual Studio 2005/2008, добавляя дополнительные пункты меню и в панель инструментов (смотри рисунок 4). Рисунок 4 — Панели инструментов, добавляемые Intel Parallel Studio в Visual Studio

В следующих параллельных заметках мы будем использовать инструмент IntelParallel Inspector из комплекта Intel Parallel Studio для проверки создаваемого параллельного кода на наличие параллельных ошибок. А также Intel Parallel Amplifier для оптимизации. Компилятор Intel Parallel Composer нам не обязателен, но мы будем компилировать OpenMP приложения им. В качестве преимущества можно назвать поддержку Intel Parallel Composer версии стандарта OpenMP 3.0, в то время как компилятор из Visual Studio 2005/2008 поддерживает только OpenMP 2.0. Также Intel C++ дает некоторые дополнительные возможности по статическому анализу параллельного кода, о чем можно прочитать в статье.

Для компиляции приложения с использованием Parallel Composer следует сделать активным компилятором Intel C++. Это можно осуществить используя кнопку «Use Intel C++» на панели инструментов, как показано на рисунке 5. Рисунок 5 — Выбор компилятора Intel C++

Теперь для сборки приложения будет использоваться компилятор Intel C++. Да, если после компиляции и запуска приложения вы увидите сообщение, подобное тому что показано на рисунке 6, то не расстраивайтесь. Рисунок 6 — Ошибка запуска тестового приложения после перекомпиляции с использованием Intel C++

Попробуйте просто перезапустить Visual Studio, чтобы в силу вступили изменения которые прописывает Parallel Studio в среду окружения. Если и это не поможет, воспользуйтесь ручной установкой окружения, запустив соответствующие командные фалы. Они доступны из меню пуск, как показано на рисунке 7. Рисунок 7 — Установка настроек среды

Закончим пока на этом первое знакомство с инструментами. Скачивайте и устанавливайте Intel Parallel Studio. Попробуйте собрать какую-нибудь свою простую программу с использованием Intel C++.

habrahabr.ru

OpenMP Clauses

Эта документация перемещена в архив и не поддерживается.

Visual Studio 2015

 

Самая актуальная документация по Visual Studio 2017: Документация по Visual Studio 2017.

Ссылки на предложения, используемые в OpenMP API.

Visual C++ поддерживает следующие предложения OpenMP.

ПредложениеОписание
copyinПозволяет потокам обращаться к значению главного потока, для threadprivate переменной.
copyprivateУказывает, что одна или несколько переменных должны совместно используются всеми потоками.
defaultЗадает поведение неограниченного переменные в области параллельной обработки.
firstprivateУказывает, что каждый поток должен иметь свой собственный экземпляр переменной, и что переменная должна быть инициализирована со значением переменной, так как она существует до параллельной конструкции.
ЕслиУказывает, следует ли выполнять цикл параллельно или последовательно.
lastprivateУказывает, что версия контекст внешней переменной приравнивается к закрытой версии поток выполняет последней итерации (цикл for конструкция) или последний раздел (#pragma разделов).
nowaitПереопределяет неявно в директиве барьера.
num_threadsЗадает число потоков в команде потока.
упорядоченныеТребуется на параллельный для инструкции Если упорядоченных директива будет использоваться в цикле.
privateУказывает, что каждый поток должен иметь свой собственный экземпляр переменной.
СокращениеУказывает, что одна или несколько переменных, являющиеся собственными для каждого потока субъекта операцию редукции в конце области параллельной обработки.
расписаниеПрименяется к для директивы.
ОбщиеУказывает, что одна или несколько переменных должны совместно используются всеми потоками.

OpenMPДирективы

msdn.microsoft.com

OpenMP Functions

Эта документация перемещена в архив и не поддерживается.

Visual Studio 2015

 

Самая актуальная документация по Visual Studio 2017: Документация по Visual Studio 2017.

Ссылки на функции, используемые в OpenMP API.

OpenMP Стандартная реализация Visual C++ включает в себя следующие функции.

ФункцияОписание
omp_destroy_lockОтменяет инициализацию блокировки.
omp_destroy_nest_lockОтменяет инициализацию вкладываемых блокировок.
omp_get_dynamicВозвращает значение, указывающее, если количество потоков в последующих параллельной области может настраиваться по времени выполнения.
omp_get_max_threadsВозвращает целое число, равное или больше, чем количество потоков, которые были бы доступны, если область параллельной без num_threads были определены в этот момент в коде.
omp_get_nestedВозвращает значение, указывающее, включена ли вложенный параллелизм.
omp_get_num_procsВозвращает количество процессоров, доступных при вызове функции.
omp_get_num_threadsВозвращает число потоков в параллельной области.
omp_get_thread_numВозвращает количество потоков потока, выполняющегося в его команде потока.
omp_get_wtickВозвращает число секунд между тактов процессора.
omp_get_wtimeВозвращает значение в секундах времени, прошедшего с какой-то момент.
omp_in_parallelВозвращает ненулевое значение, если вызывается из в параллельной области.
omp_init_lockИнициализирует простые блокировки.
omp_init_nest_lockИнициализирует блокировки.
omp_set_dynamicУказывает, что количество потоков в последующих параллельной области могут быть изменены при время выполнения.
omp_set_lockБлоки потоков выполнения, пока блокировка не освободится.
omp_set_nest_lockБлоки потоков выполнения, пока блокировка не освободится.
omp_set_nestedВключает вложенные параллелизма.
omp_set_num_threadsЗадает число потоков в последующих параллельных регионов, если иное не переопределено num_threads предложения.
omp_test_lockПытается установить блокировку, но не блокирует выполнение потока.
omp_test_nest_lockПопытка задать вкладываемых блокировок, но не блокирует выполнение потока.
omp_unset_lockОсвобождает блокировку.
omp_unset_nest_lockОсвобождает блокировку вкладываемых.

Справочник по библиотеке

msdn.microsoft.com

Ускоряем OpenMP в Visual C++ 2010 / Хабрахабр

Одним из популярных и дешёвых средств реализации многопоточных вычислений на языке C++ является OpenMP.

Достоинства технологии очевидны: простота; малые, и легко отключаемые изменения в коде; поддержка от авторов самых популярных компиляторов:

  • Visual C++
  • GCC 4.2
  • Intel C++ Compiler
Проверка боем проходит успешно, и вот распараллеленный код проникает в самые укромные уголки проекта, бьёт все рекорды производительности, выдавая шикарную статистику, подтверждающую успешность релиза.

Проходит пара лет, вы успешно мигрируете на Visual Studio 2010,… и обнаруживаете себя сидящим в луже. Если вчера обработка большого массива данных на машинах с многоядерными процессорами проходила за считанные секунды, то сегодня наличие любого фонового приложения, занимающего собственными вычислениями одно или несколько ядер, практически вешает приложение.

Почему так происходит, и как с этим бороться?

В новой реализации OpenMP перед тем, как выйти из активной области в состояние Idle, ваша программа будет ждать завершения операций ввода/вывода, причём ждать с помощью активного SpinWait.

Т.е. если мы с помощью OMP создали N потоков (по 1 на ядро), и неожиданно выяснили, что одно из ядер занято другим приложением, то с большой вероятностью на одном ядре будут выполняться 2 и больше потоков, переключение между которыми будет перемежаться 200-миллисекундными паузами.

Но в рассчётных программах мы не хотим никаких дополнительных синхронизаций! Разработчики Intel об этом знают, и предлагают пользователю самому заботиться о дополнительных ограничениях с помощью опции kmp_set_blocktime(). К сожалению, их коллеги из Microsoft решили не путать пользователей лишними настройками.

Если переписывать программу на честный threading pool лень или не позволяет религия — предлагаю воспользоваться моим опытом… даунгрейда OpenMP на оригинальную версию из Microsoft Visual Studio 2005. Также инструкция подходит для Visual Studio 2008 с минимальными изменениями.

Во-первых, скопируем в отдельную папку vcomp.lib, vcompd.lib из комплекта Visual C++ 2005 (можно ссылаться напрямую на установленный дистрибутив, но это не так удобно). Заходим в свойства использующих OpenMP проектов, и добавляем в «Additional Library Directories» нашу директорию. Вуаля — теперь проект линкуется с «правильной», быстро работающей версией OpenMP.

Но это ещё не все. Заменим включение <omp.h> заголовочным файлом следующего содержания:

#pragma once #include <omp.h> #ifndef __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX #define __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX "Microsoft.VC80" #endif #ifndef _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN #define _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "1fc8b3b9a1e18e3b" #endif #ifndef __OMP_CRT_ASSEMBLY_VERSION #define __OMP_CRT_ASSEMBLY_VERSION "8.0.50727.762" #endif #if defined(_DEBUG) #if defined(_M_IX86) #pragma comment(linker,"/manifestdependency:\"type='win32' " \ "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ "version='" __OMP_CRT_ASSEMBLY_VERSION "' " \ "processorArchitecture='x86' " \ "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") #elif defined(_M_AMD64) #pragma comment(linker,"/manifestdependency:\"type='win32' " \ "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ "version='" __OMP_CRT_ASSEMBLY_VERSION "' " \ "processorArchitecture='amd64' " \ "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") #elif defined(_M_IA64) #pragma comment(linker,"/manifestdependency:\"type='win32' " \ "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ "version='" __OMP_CRT_ASSEMBLY_VERSION "' " \ "processorArchitecture='ia64' " \ "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") #endif #else // _DEBUG #if defined(_M_IX86) #pragma comment(linker,"/manifestdependency:\"type='win32' " \ "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ "version='" __OMP_CRT_ASSEMBLY_VERSION "' " \ "processorArchitecture='x86' " \ "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") #elif defined(_M_AMD64) #pragma comment(linker,"/manifestdependency:\"type='win32' " \ "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ "version='" __OMP_CRT_ASSEMBLY_VERSION "' " \ "processorArchitecture='amd64' " \ "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") #elif defined(_M_IA64) #pragma comment(linker,"/manifestdependency:\"type='win32' " \ "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ "version='" __OMP_CRT_ASSEMBLY_VERSION "' " \ "processorArchitecture='ia64' " \ "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") #endif #endif // _DEBUG

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

Значения __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX, _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN и __OMP_CRT_ASSEMBLY_VERSION взяты из <crtassem.h>, входящего в поставку Visual C++ 2005. Если у вас стоит другая версия (например, не установлен SP1), то указанные числа нужно заменить на собственные значения

Проект по-прежнему не собирается — сейчас студия возмущена до предела тем, что не определён символ __You_must_link_with_Microsoft_OpenMP_library.

Да, это был очень тонкий намёк со стороны компилятора.

Посмотрим на содержимое сгенерированного .obj-файла. На мой взгляд, лучше всего для этого подойдёт утилита objconv в режиме дизассемблера.

Выясняем, что нам нужно определить переменную размера byte с указанным именем. К сожалению, в C и C++ мы не сможем с точностью воссоздать импортируемый символ, поэтому придётся воспользоваться MASM32.

Добавляем бессмысленную переменную:

PUBLIC __You_must_link_with_Microsoft_OpenMP_library data segment __You_must_link_with_Microsoft_OpenMP_library db 1 data ends end

компилируем:

ml /c antiomp.asm

и полученный на выходе antiomp.obj добавляем в Additional Input проектов, использующих OpenMP.

Всё — у нас должен был получиться рабочий код. Проверить версию OpenMP можно двумя способами:

  1. запустить приложение, подцепиться отладчиком и найти в списке загруженных модулей (Debug|Windows|Modules) библиотеку OpenMP
  2. попытаться найти в исполняемых файлах подстроку vcomp100. Если всё сделано по инструкции, то этой строчки быть не должно

Приятного параллельного программирования!

habrahabr.ru


Смотрите также