Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
31
Добавлен:
19.04.2015
Размер:
145.26 Кб
Скачать

Вывод алфавита Корректно:

if (omp_get_dynamic())

omp_set_dynamic(0);//запрет на динамическое изменение omp_set_num_threads(2);

//omp_set_num_threads(4);

#pragma omp parallel private(i)

{int LettersPerThread = 26 / omp_get_num_threads(); int ThisThreadNum = omp_get_thread_num();

int StartLetter = 'a' + ThisThreadNum * LettersPerThread;

int EndLetter = 'a' + ThisThreadNum * LettersPerThread + LettersPerThread;

for (int i=StartLetter; i<EndLetter; i++)

printf ("%c", i);

}

Выведет все 26 букв

Лекция 9. Захарова И.Г., Кафедра ПО

11

 

Одновременное использование общего ресурса

Пример - операция вывода (через printf) строки на экран не

является атомарной.

два (и более) треда будут выводить свои символы

одновременно.

Аналогично для стандартного потока вывода cout,

для любого другого объекта, доступного нескольким тредам.

Для корректного выполнения действия, изменяющего состояние таких объектов из нескольких тредов, необходимо обеспечить:

в каждый момент времени действие выполняется только одним из тредов.

Для этого можно использовать директиву critical.

#pragma omp parallel num_threads(4)

{#pragma omp critical

{printf("Hello World\n");

}

}

Лекция 9. Захарова И.Г., Кафедра ПО

12

Незащищенный доступ к общей памяти

Для корректного выполнения действия, изменяющего состояние общей памяти из нескольких тредов, необходимо обеспечить:

в каждый момент времени действие выполняется только одним из тредов.

Для этого можно использовать директиву atomic.

Лекция 9. Захарова И.Г., Кафедра ПО

13

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

int a = 0;

#pragma omp parallel

{

} a++; Корректно:

int a = 0;

#pragma omp parallel

{

#pragma omp atomic a++;

}

или

int a = 0;

#pragma omp parallel reduction(+:a)

{

a++;

}

Лекция 9. Захарова И.Г., Кафедра ПО

14

 

Отсутствие директивы flush Директива flush неявно не выполняется :

При входе в параллельную секцию директивы for.

При входе и при выходе из секции директивы master.

При входе в параллельную секцию директивы sections.

При входе в секцию директивы single.

При выходе из секции директивы for, single или sections, если есть опция nowait.

Поэтому нужно явное указание!

Лекция 9. Захарова И.Г., Кафедра ПО

15

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

int a = 0;

#pragma omp parallel num_threads(2)

{

a++;

#pragma omp single

{

cout << a << endl;

}

}

Корректно (почти):

int a = 0;

#pragma omp parallel num_threads(2)

{

a++;

#pragma omp single

{

#pragma omp flush(a) cout << a << endl;

}

}

Недостаток – нет синхронизации, поэтому на выходе возможно 1 или 2

Лекция 9. Захарова И.Г., Кафедра ПО

16

 

Отсутствие явной синхронизации тредов

(как в последнем коде)

Корректно : int a = 0;

#pragma omp parallel num_threads(2)

{

#pragma omp atomic a++;

#pragma omp barrier //явная синхронизация! #pragma omp single

{

cout<<a<<endl;

}

}

Лекция 9. Захарова И.Г., Кафедра ПО

17

Не инициализированы локальные переменные

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

int a = 0;

#pragma omp parallel private(a)

{

 

 

 

a++;

Корректно :

}

 

 

 

int a = 0;

 

 

#pragma omp parallel private(a)

 

 

{

 

 

a = 0;

 

 

a++;

 

 

}

 

 

Синхронизация не нужна – у каждого

 

 

треда своя копия переменной a

Лекция 9. Захарова И.Г., Кафедра ПО

18

 

Ограничения для локальных переменных Если требуется создать локальную копию объекта, массива или ссылочной переменной, то соответствующая ссылка должна быть

общей переменной.

Локальные переменные явно не выделены Если переменная не помечена как локальная,

то она используется как общая по умолчанию.

Лекция 9. Захарова И.Г., Кафедра ПО

19

Не определен порядок итераций цикла Некорректно:

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]);

Теоретически программа должна вывести нули.

НО: на двухпроцессорной машине будет выведено некоторое количество нулей и пятерок - итерации (как правило) делятся между тредами пополам.

Лекция 9. Захарова И.Г., Кафедра ПО

20

 

Соседние файлы в папке Параллельное программирование (лекции)