ORDERED Directive

Назначение:

  • Директива ORDERED устанавливает, что итерации вложенного цикла будут выполнены в таком же порядке, что и при последовательном выполнении
  • Каждая нить перед выполнением своей порции итераций ждет завершения предыдущих порций.
  • Используется в теле цикла for определенного как ORDERED

Формат:

#pragma omp for ordered [clauses...] (loop region) #pragma omp ordered newline structured_block (endo of loop region)

Огранчения:

  • Директива ORDERED может появляться только в контексте расширения директивы for/parallel for
  • Только один поток может выполняться в секции ORDERED в момент времени
  • Запрещается переход в блок или из блока ORDERED
  • Итерация цикла не должна выполняться той же самой директивой ORDERED более чем один раз, и не должна выполняться более чем одна директива ORDERED
  • Цикл, содержащий директиву ORDERED, должен быть определен клаузой ORDERED

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

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

void TestOrdered()

{

int a[20], i = 0;

#pragma omp parallel default(shared) private(i) num_threads(10)

{

 

#pragma omp for

for (i = 0; i < 20; i++)

a[i] = i * 2;

 

#pragma omp for ordered

for (i = 0; i < 20; i++)

{

a[i] = i + 8;//concurrent performing

 

#pragma omp ordered

printf_s("a[%d] = %d\n",i,a[i]);//serial, ordered performing

}

}

} Другой пример показывает различие в использовании директив ordered и critical.

void TestOrdered()

{

int a[20], i = 0;

#pragma omp parallel default(shared) private(i) num_threads(10)

{

 

#pragma omp for

for (i = 0; i < 20; i++)

a[i] = i * 2;

 

#pragma omp for ordered

for (i = 0; i < 20; i++)

{

a[i] = i + 8;//concurrent performing

 

#pragma omp critical

printf_s("critical:a[%d] = %d\n",i,a[i]);

//not ordered performing

 

#pragma omp ordered

printf_s("\t\t\tordered: a[%d] = %d\n",i,a[i]);

//serial, ordered performing

}

}

}

Применение директивы ordered может вызвать проблемы у начинающих программистов. Приведем пример кода:

Некорректно:

#pragma omp parallel for ordered for (int i = 0; i < 10; i++) { myFunc(i); }

Корректно:

#pragma omp parallel for ordered for (int i = 0; i < 10; i++) { #pragma omp ordered { myFunc(i); } }

Суть ошибки заключается в том, что в первом примере выражение ordered будет просто проигнорировано, поскольку не указана область его действия. Цикл будет выполняться в произвольном порядке.

Вторая особенность

Применение директивы диктуется зависимостью одной итерации от результата выполнения предыдущих итераций. Рассмотрим пример.

Некорректно:

int* arr = new int[10]; for(int i = 0; i < 10; i++) arr[i] = i; #pragma omp parallel for for (int i = 1; i < 10; i++) arr[i] = arr[i - 1]; for(int i = 0; i < 10; i++) printf("narr[%d] = %d", i, arr[i]);

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

Корректно:

int* arr = new int[10]; for(int i = 0; i < 10; i++) arr[i] = i; #pragma omp parallel for ordered for (int i = 1; i < 10; i++) { #pragma omp ordered arr[i] = arr[i - 1]; } for(int i = 0; i < 10; i++) printf("narr[%d] = %d", i, arr[i]);

 








Дата добавления: 2015-02-03; просмотров: 904;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.005 сек.