OpenMP и Visual Studio
Автор: Сухинов Антон
Источник: http://iproc.ru/programming/openmp-visual-studio/
Автор: Сухинов Антон
Источник: http://iproc.ru/programming/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 реализован посредством следующих компонентов:
В бесплатной Visual Studio Express перечисленные библиотеки отсутствуют.
Если вы хотите создавать параллельные OpenMP-программы под Windows, то самый удобный способ – это воспользоваться Visual Studio 2005/2008/2010 Professional. Напоминаю, что она бесплатна для студентов и аспирантов. Кроме того, вы можете купить Visual Studio Professional за $600 (конечно, существует ещё и третий вариант, но мы о нём не будем говорить).
Если на вашем компьютере установлена версия Professional – переходите к следующему разделу статьи. В этом разделе рассмотрим случай, когда по каким-либо причинам вы вынуждены использовать Visual Studio Express.
Visual Studio Express – это бесплатная урезанная версия Visual Studio. Нас будет интересовать версия 2008 года. Скачать её можно отсюда: http://www.microsoft.com/exPress/download/. Естественно, программировать будем на C++, поэтому выбирайте Visual C++ 2008.
Программа установки будет загружать данные из Интернета (примерно 100 мегабайт), поэтому вы можете сэкономить немного трафика, отключив установку Microsoft Silverlight и Microsoft SQL Server, если они вам не требуются.
После установки 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»).
После того, как вы выполнили шаги, описанные в предыдущем разделе, уже не важно, какой версией Visual Studio вы пользуетесь. Покажу шаг за шагом, как создать проект с поддержкой OpenMP в этой среде разработки. Прежде всего, нужно запустить Visual Studio, и выбрать File→New→Project... Появится окно создания проекта. Выберите тип проекта «Win32», шаблон – «Win32 Console Application». Введите осмысленное имя проекта, выберите папку для хранения проекта, уберите галочку «Create directory for solution»:
Рисунок 2. Окно создания проекта
Нажмите кнопку «OK», появится окно настройки будущего проекта. Выберите вкладку «Application Settings», и включите галку «Empty project»:
Рисунок 3. Окно настройки будущего проекта
По нажатию кнопки «Finish» проект будет создан. Никаких видимых изменений в главном окне Visual Studio не произойдёт. Только имя проекта в заголовке окна как бы говорит нам о том, что мы работаем с проектом.
Теперь нажмите Project→Add New Item, появится окно добавления элементов в проект. Добавьте .cpp-файл в проект:
Рисунок 4. Окно добавления элементов в проект
После этого вам будет предоставлено окно для ввода исходного кода программы. Будем выполнять тесты на следующем коде, проверяющем различные аспекты функционирования OpenMP:
Листинг 1. Простейшая программа, использующая OpenMP
#include <iostream>
#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;
}
Запустите программу, нажав Debug→Start Without Debugging. Если всё было сделано правильно, программа откомпилируется (если спросит вас, компилировать ли, нажмите «Yes»), затем запустится и выведет test = 999:
Рисунок 5. Результат работы программы из листинга 1
«Как же так?! – скажете вы – Ведь программа должна была вывести ноль, причём дважды!». Дело в том, что OpenMP ещё не включен, и поэтому соответствующие директивы были проигнорированы компилятором.
Для включения OpenMP нажмите Project→OMP Properties (OMP – имя проекта из моих примеров). Слева вверху появившегося окна выберите «All Configurations» и в разделе Configuration Properties→C/C++→Language включите «OpenMP Support»:
Рисунок 6. Включаем OpenMP в свойствах проекта
После этого снова запустите программу, нажав Debug→Start Without Debugging. На этот раз программа выведет test = 0 дважды:
Рисунок 7. Результат работы программы из листинга 1 с включённым OpenMP
Ура! OpenMP работает.
Примечание. Если вы используете Visual Studio Express, то выберите текущую конфигурацию «Release», иначе работать не будет (читайте далее):
Рисунок 8. Выбор текущей конфигурации
Как было сказано ранее, даже после установки Windows SDK у нас не будет в наличии необходимой для отладки библиотеки vcomp90d.dll, поэтому мы пока не можем отлаживать OpenMP программу в Visual Studio Express. Простое копирование имеющейся библиотеки vcomp90.dll и переименование её в vcomp90d.dll не сработает, ибо не совпадёт контрольная сумма и версия, указанные во встраиваемом в exe-файл манифесте. Поэтому будем «копать» с противоположной стороны.
При компиляции в конфигурации «Debug» («Отладка»), заголовочный файл omp.h требует библиотеку vcompd.lib (она у нас имеется), которая, в свою очередь, требует vcomp90d.dll (отсутствует). Лицензия не позволяет нам использовать в приложениях модифицированные заголовочные файлы от Microsoft, поэтому вместо модификации omp.h включим его в нашу программу следующим образом, чтобы он не догадался о включённом режиме отладки:
Листинг 2. Включаем omp.h «хитрым» способом
#include <iostream>
#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;
}
Приведённого действия не достаточно для того, чтобы всё работало (пока мы исправили лишь манифест, встраиваемый в программу). Дело в том, что Visual Studio в режиме отладки по прежнему автоматически (из-за включённого OpenMP) прилинковывает vcompd.lib, требующую vcomp90d.dll. Чтобы это исправить, снова зайдите в настройки проекта (Project→OMP Properties), выберите на этот раз Configuration: «Debug». В разделе Configuration Properties→Linker→Input укажите, что vcompd.lib прилинковывать не нужно, а vcompd.lib – нужно:
Рисунок 9. Заменяем библиотеку в свойствах проекта
Проверим теперь, работает ли отладка, и действительно ли программа работает параллельно. Поставьте точку останова на строке с выводом значения переменной. Для этого нажмите левой кнопкой мыши не серую полоску слева от исходного кода:
Рисунок 10. Точка останова
После этого запустите программу в режиме отладки: Debug→Start Debugging (не забудьте вернуть текущую конфигурацию «Debug», см. рисунок 8). Программа запустится – и сразу же остановится на точке останова. Во вкладке «Threads» мы видим, что программа действительно работает, используя два потока:
Рисунок 11. Отладка OpenMP-программы в Visual Studio Express
Если вы не знаете, как создавать параллельные программы при помощи OpenMP, советую прочесть спецификацию, там всё подробно описано: http://www.openmp.org/mp-documents/spec30.pdf.