OpenMP и Visual Studio
OpenMP позволяет легко создавать параллельные программы для систем с общей памятью (многоядерных и многопроцессорных). В этой статье я расскажу о том, как включить OpenMP в самой распространённой среде программирования — Visual Studio. Согласно официальной версии Microsoft, OpenMP поддерживается только в версиях Professional среды разработки Visual Studio 2005/2008/2010. Однако бесплатная Visual Studio Express обладает тем же компилятором, что и версия Professional. Поэтому после небольшой «доработки напильником» параллельные OpenMP-программы будут компилироваться и, главное, работать даже в Visual Studio Express.
OpenMP от Microsoft реализован посредством следующих компонентов:
- компилятор C++, входящий в состав Visual Studio;
- заголовочный файл
omp.h
; - библиотеки стадии компиляции:
vcomp.lib
иvcompd.lib
(последняя используется для отладки); - библиотеки времени выполнения:
vcomp90.dll
иvcomp90d.dll
. Цифры в названии могут различаться: в Visual Studio 2005 вместо90
стоя́т цифры80
.
В бесплатной Visual Studio Express перечисленные библиотеки отсутствуют.
OpenMP и Visual Studio Express
Если вы хотите создавать параллельные OpenMP-программы под Windows, то самый удобный способ — это воспользоваться Visual Studio 2005/2008/2010 Professional. Напоминаю, что она бесплатна для студентов и аспирантов. Кроме того, вы можете купить Visual Studio Professional за $600 (конечно, существует ещё и третий вариант, но мы о нём не будем говорить).
Если на вашем компьютере установлена версия Professional — переходите к следующему разделу статьи. В этом разделе рассмотрим случай, когда по каким-либо причинам вы вынуждены использовать Visual Studio Express.
Со времени написания этой статьи прошло много времени. Чтобы не потерять актуальность, скажу, что вышла версия Visual Studio 2010 Express. Однако, я её пока не испытывал.
Visual Studio Express — это бесплатная урезанная версия Visual Studio. Нас будет интересовать версия 2008 года. Скачать её можно отсюда: http://www.microsoft.com/exPress/download/. Естественно, программировать будем на C++, поэтому выбирайте Visual C++ 2008.
Программа установки будет загружать данные из Интернета (примерно 100 мегабайт), поэтому вы можете сэкономить немного трафика, отключив установку Microsoft Silverlight и Microsoft SQL Server, если они вам не требуются.
Со времени написания этой статьи вышел новый SDK: Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1. К сожалению, я его не испытывал. Все существующие SDK перечислены на этой странице.
После установки Visual Studio Express нам понадобится добавить в неё OpenMP-компоненты. Легальный бесплатный способ сделать это — установить Windows SDK for Windows Server 2008 and .NET Framework 3.5. Во время установки этого пакета программ будет произведено обновление Visual Studio. Процесс обновления не смотрит, какая именно версия Visual Studio у вас установлена (Express или Professional), поэтому во время установки будут «случайно» добавлены недостающие компоненты.
Так как мы ставим Windows SDK только ради OpenMP, то нам не нужен тот гигабайт документации, который идёт в комплекте. Рекомендую оставить только следующие элементы:
Рисунок 1. Необходимые нам компоненты SDK
К сожалению, в состав SDK не входит
библиотека vcomp90d.dll
, поэтому на
данный момент в Visual Studio Express вы сможете
запускать только OpenMP-программы,
откомпилированные в режиме Release.
Я нашёл способ обойти и это ограничение, об
этом читайте далее (раздел «Отладка
OpenMP-программы в Visual Studio Express»).
Использование OpenMP в Visual Studio
После того, как вы выполнили шаги, описанные в предыдущем разделе, уже не важно, какой версией Visual Studio вы пользуетесь. Покажу шаг за шагом, как создать проект с поддержкой OpenMP в этой среде разработки. Прежде всего, нужно запустить Visual Studio, и выбрать File → New → Project... Появится окно создания проекта. Выберите тип проекта «Win32», шаблон — «Win32 Console Application». Введите осмысленное имя проекта, выберите папку для хранения проекта, уберите галочку «Create directory for solution»:
Нажмите кнопку «OK», появится окно настройки будущего проекта. Выберите вкладку «Application Settings», и включите галку «Empty project»:
По нажатию кнопки «Finish» проект будет создан. Никаких видимых изменений в главном окне Visual Studio не произойдёт. Только имя проекта в заголовке окна как бы говорит нам о том, что мы работаем с проектом.
Теперь нажмите Project → Add New Item,
появится окно добавления элементов
в проект. Добавьте .cpp
-файл
в проект:
После этого вам будет предоставлено окно для ввода исходного кода программы. Будем выполнять тесты на следующем коде, проверяющем различные аспекты функционирования OpenMP:
#include <omp.h>
using namespace std;
int main(int argc, char **argv)
{
int test( 999 );
omp_set_num_threads( 2 );
#pragma omp parallel reduction(+:test)
{
#pragma omp critical
cout << "test = " << test << endl;
}
return EXIT_SUCCESS;
}
Листинг 1. Простейшая программа, использующая OpenMP
Запустите программу, нажав Debug →
Start Without Debugging. Если всё было сделано
правильно, программа
откомпилируется (если спросит вас,
компилировать ли, нажмите «Yes»), затем
запустится и выведет test = 999
:
«Как же так?! — скажете вы — Ведь программа должна была вывести ноль, причём дважды!». Дело в том, что OpenMP ещё не включен, и поэтому соответствующие директивы были проигнорированы компилятором.
Для включения OpenMP нажмите Project → OMP Properties (OMP — имя проекта из моих примеров). Слева вверху появившегося окна выберите «All Configurations» и в разделе Configuration Properties → C/C++ → Language включите «OpenMP Support»:
После этого снова запустите
программу, нажав Debug → Start Without Debugging. На этот раз
программа выведет test = 0
дважды:
Ура! OpenMP работает.
Примечание. Если вы используете Visual Studio Express, то выберите текущую конфигурацию «Release», иначе работать не будет (читайте далее):
Рисунок 8. Выбор текущей конфигурации
Отладка OpenMP-программы в Visual Studio Express
Как было сказано ранее, даже после
установки Windows SDK у нас не будет
в наличии необходимой для отладки
библиотеки vcomp90d.dll
, поэтому мы
пока не можем отлаживать OpenMP программу
в Visual Studio Express. Простое копирование
имеющейся библиотеки vcomp90.dll
и
переименование её в vcomp90d.dll
не
сработает, ибо не совпадёт контрольная
сумма и версия, указанные во встраиваемом
в exe-файл манифесте. Поэтому будем
«копать» с противоположной
стороны.
При компиляции в конфигурации «Debug»
(«Отладка»), заголовочный файл omp.h
требует библиотеку vcompd.lib
(она
у нас имеется), которая, в свою очередь,
требует vcomp90d.dll
(отсутствует).
Лицензия не позволяет нам использовать
в приложениях модифицированные
заголовочные файлы от Microsoft, поэтому
вместо модификации omp.h
включим его
в нашу программу следующим образом,
чтобы он не догадался о включённом
режиме отладки:
#ifdef _DEBUG
#undef _DEBUG
#include <omp.h>
#define _DEBUG
#else
#include <omp.h>
#endif
using namespace std;
int main(int argc, char **argv)
{
int test( 999 );
omp_set_num_threads( 2 );
#pragma omp parallel reduction(+:test)
{
#pragma omp critical
cout << "test = " << test << endl;
}
return EXIT_SUCCESS;
}
Листинг 2. Включаем omp.h
«хитрым»
способом
Приведённого действия не достаточно
для того, чтобы всё работало (пока мы
исправили лишь манифест, встраиваемый
в программу). Дело в том, что Visual Studio
в режиме отладки по прежнему
автоматически (из-за включённого OpenMP)
прилинковывает vcompd.lib
,
требующую vcomp90d.dll
. Чтобы это
исправить, снова зайдите в настройки
проекта (Project → OMP Properties), выберите на этот
раз Configuration: «Debug». В разделе Configuration
Properties → Linker → Input укажите, что
vcompd.lib
прилинковывать не нужно,
а vcompd.lib
— нужно:
Проверим теперь, работает ли отладка, и действительно ли программа работает параллельно. Поставьте точку останова на строке с выводом значения переменной. Для этого нажмите левой кнопкой мыши не серую полоску слева от исходного кода:
Рисунок 10. Точка останова
После этого запустите программу в режиме отладки: Debug → Start Debugging (не забудьте вернуть текущую конфигурацию «Debug», см. рисунок 8). Программа запустится — и сразу же остановится на точке останова. Во вкладке «Threads» мы видим, что программа действительно работает, используя два потока:
P.S.
Если вы не знаете, как создавать параллельные программы при помощи OpenMP, советую прочесть спецификацию, там всё подробно описано: http://www.openmp.org/mp-documents/spec30.pdf.