(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Параллельное программирование для многоядерных систем с помощью OpenMP

Источник: codingclub

История

Самым значимым событием 2005 года стало появление многоядерных процессоров. К тому времени классические одноядерные системы исчерпали свой потенциал, поскольку не давали нужной производительности за счет повышения частот, мало того разработчики архитектур столкнулись с проблемой нестабильности и повышенного тепловыделения. Все это волей-неволей способствовало появлению революционных многоядерных процессоров. Идея этих процессоров предельно проста: в одном процессоре интегрировано более одного ядра. Такой подход способствует появлению более производительных процессоров без повышения частот.

OpenMP

Тем не менее, на сегодняшний день не так уж и много приложений (особенно игр), которые полноценно используют многопроцессорные системы. Если Ваше приложение не использует несколько ядер, то соответственно и прироста быстродействия не будет. Именно здесь появляется на сцене OpenMP, технология, с помощью которой можно легко и быстро создавать мультипоточные приложения на C++ и соответственно существенно повысить производительности. Данная технология была разработана в 1997 году и изначально базировалась на языке Fortran. Сегодня она включена в язык C++ и доступна в Visual Studio 2005 (версия 2.0), а также на платформе XBOX 360.
Прежде чем приступать к коду, нужно активизировать реализованные в компиляторе средства OpenMP. Для этого в свойствах проекта C/C++ -> Language -> OpenMP ставим Yes(/openmp). Встретив параметр /openmp компилятор определяет символ _OPENMP, с помощью которого мы сможем определить используется ли данная технология в нашем приложении или нет. Так же, во избежание ошибок, в проект следует подключить хедер omp.h, который содержит нужные нам функции из vcomp.dll (или vcompd.dll в отладочной версии, которая содержит дополнительные сообщения об ошибках), манифесты и т.п.

"Helloworld"

OpenMP достаточно прост в использовании, он состоит из набора прагм и функций из omp.h. Прагмы - это указатели компилятору разбивать код на блоки, которые будут выполняться параллельно. Если openmp выключен, компилятор проигнорирует прагмы, а код останется вполне работоспособным. Все это дает возможность писать универсальный, переносимый код для реализации программ на различных архитектурах и системах. Спецификация OpenMP поддерживается такими поставщиками как Sun, Intel и IBM.
Все директивы начинаются с #pragma omp. Самая важная и распространенная директива - parallel. Она создает параллельный регион для следующего за ней блока. В качестве примера рассмотрим классический "Hello world":
Код:
int main()
{
 #pragma omp parallel
{
 printf("Hello world\n");
}
return 0;
}
При выполнении на двуядерной системе мы получим результат:

Код:
Hello world
Hello world

Рассмотрим более сложный пример, в котором используем конструкцию #pragma omp for, которая сообщает, что при выполнении цикла for в параллельном регионе итерации цикла должны быть распределены между потоками группы:
Код:
#pragma omp parallel
{
#pragma omp for
 for(int i < 0; i < num_Particles; i++) {
        Action(vec[i]);
}
}
Отметим очень важное замечание: если убрать из конструкции #pragma omp for, то каждый поток полностью выполнит цикл, таким образом будет выполнено много ненужной работы. В OpenMP также имеется возможность более краткой записи прагм #pragma omp parallel и #pragma omp for:
 
Код:
#pragma omp parallel for for(int i < 0; i < num_Particles; i++) {Action(vec[i]);
}

Барьеры и nowait

Барьеры являются одним из видов синхронизации. При обнаружении барьера поток останавливается и ждет пока все остальные потоки не окажутся на этом же барьере. Например, при выполнении цикла выше мы столкнулись с неявной барьерной синхронизацией, сами не заметив того. В конце цикла стоит барьер, который приостанавливает выполнение освободившихся потоков до тех пор, пока не освободятся другие потоки, обрабатывающие итерации этого же цикла. В некоторых случаях возникает потребность отключать синхронизацию, для этого существует оператор nowait, приведем пример, где это может быть выгодно:
Код:
#pragma omp parallel
{
#pragma omp for nowait
            for(int i = 0; i < 5000; i++) {
                        // …
            }
#pragma omp for
            for(int j = 0; j < 1000; j++) {
                        // …
            }
#pragma omp barrier
             some_func();
}В этом примере потоки, которые освободились после обработки первого цикла переходят к обработке второго цикла без ожидания остальных потоков. В некоторых случаях это может повысить производительность, поскольку уменьшается время простоя потоков. Возможна и обратная ситуация, когда нам нужно организовать барьер. В примере выше функция some_func() не выполнится до тех пор, пока все потоки не выполнят предыдущие задачи (это нужно, например, при обновлении буфера кадров перед выводом его содержимого на экран).

Ограничение на циклы

В OpenMP существует ряд ограничений на циклы, которые нужно распараллелить:
1.Переменная цикла должна иметь тип integer. Беззнаковые целые числа, такие как DWORD, работать не будут.
2.Цикл должен являться базовым блоком и не может использовать goto и break (за исключением оператора exit, который завершает все приложение).
3.Инкрементная часть цикла for должно являться либо целочисленным сложением, либо целочисленным вычитанием и должно практически совпадать со значением инварианта цикла.
4.Если используется операция сравнения < или <=, переменная цикла должна увеличиваться при каждой итерации, а при использовании операции > или >= переменная цикла должна уменьшаться.

Критические разделы

С помощью критических разделов можно предотвратить одновременный доступ к одному сегменту кода из нескольких потоков. Один поток получает доступ только тогда, когда другие не обрабатывают данный код. Конструкция имеет следующий вид:
Код:
#pragma omp critical
{
     …
}Такие критические разделы называются неименованными. Существуют также именованные, которые способствуют повышению производительности приложения, поскольку блокировка будет производиться только теми потоками, которым это действительно необходимо. Выглядит следующим образом:

Код:
#pragma omp critical(some_value)
{
      …
}

Конструкция Sections

OpenMP применим не только для циклов, но и для функций. Конструкция sections используется когда необходимо выполнять блоки кода в отдельных потоках. Рассмотрим простейший пример (сортировка):
Код:
#pragma omp parallel sections
{
            #pragma omp section
            sort(array, …);
            #pragma omp section
            sort(array, …);
}
В данном примере первая директива #pragma создает параллельный регион секций, а последующие секции определяются директивой #pragma omp section. Каждой секции в параллельном регионе ставится в соответствие один поток из группы потоков, и все секции выполняются одновременно. Заметим, что каждая из функций sort выполняется полностью независимо друг от друга, это очень важно, поскольку приводит к тривиальным ошибкам, которые очень тяжело отловить. Рассмотрим пример ошибочного кода:
Код:
int n, m, q;
#pragma omp parallel sections
{
            #pragma omp section
            n = partition(array, lo, hi);
            #pragma omp section
            m = partition(array, lo, n-1); // n возможно не определен!!
            #pragma omp section
            q = partition(array, n+1, hi);  // n возможно не определен!!
}При компиляции приложения без параметра /openmp будет сгенерирована корректная последовательная версия. Одно из преимуществ OpenMP в том, что эта технология совместима с компиляторами, не поддерживающими OpenMP.
Выводы
OpenMP быстрая, простая и легкая технология с помощью которой можно использовать потенциал многоядерных систем. Всего за несколько минут обычный код можно переделать в оптимизированный, при этом остается совместимость с компиляторами, которые не поддерживают данную технологию. Возможное применение в игровых движках: particle system, collision detection, fractals, поиск путей и т. д. К сожалению, в данной статье мы коротко рассмотрели лишь малую часть возможностей данной технологии, но более подробную спецификацию вы можете найти на сайте http://www.openmp.org.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 21.12.2009 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год.
Microsoft 365 Apps for business (corporate)
Microsoft Windows Professional 10, Электронный ключ
Microsoft 365 Business Basic (corporate)
Microsoft 365 Business Standard (corporate)
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Компьютерный дизайн - Все графические редакторы
Delphi - проблемы и решения
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100