Разделы презентаций


lec09.pptx презентация, доклад

Содержание

Логические ошибкиНе подключено OpenMPПропущено parallelНекорректно:#pragma omp for ... //кодКорректно:#pragma omp parallel for ... // кодили #pragma omp parallel { #pragma omp for ... //код }Лекция 9. Захарова И.Г., Кафедра ПО

Слайды и текст этой презентации

Слайд 1Типичные ошибки по материалам статьи «32 подводных камня OpenMP при

программировании на Си++» http://software.intel.com/ru-ru/articles/32-openmp-traps-for-c-developers/
Речь об ошибках, которые не обнаруживаются

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

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

Типичные ошибки  по материалам статьи «32 подводных камня OpenMP при программировании на Си++»  http://software.intel.com/ru-ru/articles/32-openmp-traps-for-c-developers/ Речь

Слайд 2Логические ошибки
Не подключено OpenMP

Пропущено parallel
Некорректно:
#pragma omp for
... //код
Корректно:
#pragma omp

parallel for
... // код

или
#pragma omp parallel
{
#pragma

omp for
... //код
}

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

Логические ошибкиНе подключено OpenMPПропущено parallelНекорректно:#pragma omp for ... //кодКорректно:#pragma omp parallel for ... // кодили #pragma omp

Слайд 3Пропущено omp
Некорректно:
#pragma omp parallel num_threads(2)
{
#pragma single
{
printf("me\n");


}
}
Напечатает 2 раза
Корректно:
#pragma omp parallel num_threads(2)
{
#pragma omp

single
{
printf("me\n");
}
}

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

Пропущено ompНекорректно:#pragma omp parallel num_threads(2) {	 #pragma single 	{ 		printf(

Слайд 4Пропущено for
Некорректно:
#pragma omp parallel num_threads(2)
for (int i = 0;

i < 10; i++)
myFunc();
Вызовет функцию 20 раз
Корректно:
#pragma omp parallel

for num_threads(2)
for (int i = 0; i < 10; i++)
myFunc();

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

Пропущено forНекорректно:#pragma omp parallel num_threads(2) 	for (int i = 0; i < 10; i++)	 	myFunc();Вызовет функцию 20

Слайд 5Лишнее parallel
Некорректно - вызовет функцию 20 раз
#pragma omp parallel num_threads(2)


{ ... // N строк кода
#pragma omp parallel for


for (int i = 0; i < 10; i++) { myFunc(); }
}

Корректно:
#pragma omp parallel num_threads(2)
{ ... // N строк кода
#pragma omp for
for (int i = 0; i < 10; i++)
{ myFunc(); }
}

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

Лишнее parallelНекорректно - вызовет функцию 20 раз#pragma omp parallel num_threads(2) { 	... // N строк кода 		#pragma

Слайд 6Пропущено ordered
Некорректно:
#pragma omp parallel for ordered
for (int i =

0; i < 10; i++)
{ myFunc(i); }
Не указана область

– ordered игнорируется, цикл выполняется в произвольном порядке

Корректно:
#pragma omp parallel for ordered
for (int i = 0; i < 10; i++)
{
#pragma omp ordered
{ myFunc(i); }
}

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

Пропущено orderedНекорректно:#pragma omp parallel for ordered 	for (int i = 0; i < 10; i++) 		{ myFunc(i);

Слайд 7Переопределение количества тредов внутри параллельной секции
Некорректно:
#pragma omp parallel
{ omp_set_num_threads(2);


#pragma omp for
for (int i = 0; i

10; i++)
{ myFunc(); }
}

Корректно:
#pragma omp parallel num_threads(2)
{
#pragma omp for
for (int i = 0; i < 10; i++)
{ myFunc(); }
}

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

Переопределение количества тредов внутри параллельной секцииНекорректно:#pragma omp parallel { 	omp_set_num_threads(2); 	#pragma omp for 		for (int i =

Слайд 8Зависимость поведения программы от числа тредов

Число тредов:
По умолчанию, как правило,

равно числу установленных на компьютере процессоров.
Может также задаваться программистом:
функция

omp_set_num_threads,
опция num_threads,
переменная среды OMP_NUM_THREADS.
По умолчанию может оказаться разным на разных компьютерах.
Если это специально не заложено в алгоритм, то поведение кода не должно зависеть от количества выполняющих его тредов.
Распределение работы между тредами выполняет компилятор.
Можно использовать опцию schedule.

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

Зависимость поведения программы от числа тредовЧисло тредов:По умолчанию, как правило, равно числу установленных на компьютере процессоров. Может

Слайд 9Вывод алфавита
Некорректно:
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 printf ("%c", i);
}
Выведет только 24 буквы

Корректно:
omp_set_num_threads(4);
#pragma omp parallel for
for (int i = 'a'; i <= 'z'; i++)
{ printf ("%c", i); }

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

Вывод алфавитаНекорректно:omp_set_num_threads(4); #pragma omp parallel private(i) {	int LettersPerThread = 26 / omp_get_num_threads(); 	int ThisThreadNum = omp_get_thread_num(); 	int

Слайд 10Некорректное динамическое создание тредов

Переменная среды bool OMP_DYNAMIC задает возможность динамического

определения числа тредов.
Переменная имеет больший приоритет, чем опция num_threads.


?Если выполнение кода зависит от количества выполняющих его тредов, поведение программы может стать некорректным.
Спецификация OpenMP - значение OMP_DYNAMIC зависит от конкретной реализации.
Следовательно, необходимы доп. проверки.

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

Некорректное динамическое создание тредовПеременная среды bool OMP_DYNAMIC задает возможность динамического определения числа тредов. Переменная имеет больший приоритет,

Слайд 11Вывод алфавита
Корректно:
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 printf ("%c", i);
}
Выведет все 26 букв

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

Вывод алфавитаКорректно: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

Слайд 12Одновременное использование общего ресурса
Пример - операция вывода (через printf) строки

на экран не является атомарной. ? два (и более) треда

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

Для корректного выполнения действия, изменяющего состояние таких объектов из нескольких тредов, необходимо обеспечить: в каждый момент времени действие выполняется только одним из тредов.
Для этого можно использовать директиву critical.
#pragma omp parallel num_threads(4)
{ #pragma omp critical
{ printf("Hello World\n");
}
}

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

Одновременное использование общего ресурсаПример - операция вывода (через printf) строки на экран не является атомарной.  ?

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

Для корректного выполнения действия, изменяющего состояние

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

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

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

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

Слайд 14Некорректно:
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. Захарова И.Г., Кафедра ПО

Некорректно:int a = 0; #pragma omp parallel{ 	a++; }Корректно:int a = 0; #pragma omp parallel { 	#pragma

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

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

директивы master.
При входе в параллельную секцию директивы sections.
При входе в секцию директивы single.
При выходе из секции директивы for, single или sections, если есть опция nowait.
Поэтому нужно явное указание!

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

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

Слайд 16Некорректно:
int a = 0;
#pragma omp parallel num_threads(2)
{
a++;


#pragma omp single
{
cout

(почти):
int a = 0;
#pragma omp parallel num_threads(2)
{
a++;
#pragma omp single
{
#pragma omp flush(a)
cout << a << endl;
}
}

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

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

Некорректно:int a = 0; #pragma omp parallel num_threads(2) { 	a++; 	#pragma omp single 	{ 		cout

Слайд 17Отсутствие явной синхронизации тредов
(как в последнем коде)
Корректно :
int a =

0;
#pragma omp parallel num_threads(2)
{
#pragma omp atomic
a++;


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

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

Отсутствие явной синхронизации тредов(как в последнем коде)Корректно :int a = 0; #pragma omp parallel num_threads(2) { 	#pragma

Слайд 18Не инициализированы локальные переменные
Некорректно:
int a = 0;
#pragma omp parallel

private(a)
{
a++;
}
Корректно :
int a = 0;
#pragma omp

parallel private(a)
{
a = 0;
a++;
}

Синхронизация не нужна – у каждого треда своя копия переменной a

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

Не инициализированы локальные переменныеНекорректно:int a = 0; #pragma omp parallel private(a) { 	a++; }Корректно :int a =

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

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

Локальные

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

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

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

Слайд 20Не определен порядок итераций цикла
Некорректно:
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. Захарова И.Г., Кафедра ПО

Не определен порядок итераций циклаНекорректно:int* arr = new int[10]; for(int i = 0; i < 10; i++)

Слайд 21Корректно:
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]);

Программа выведет нули. 

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

Корректно:int* arr = new int[10]; for(int i = 0; i < 10; i++) 	arr[i] = i; #pragma

Слайд 22Ошибки производительности (программа работает корректно, но неэффективно)
Лишняя директива flush
Директива выполняется по

умолчанию:
В директиве barrier
При входе и при выходе из параллельной секции

директивы critical
При входе и при выходе из параллельной секции директивы ordered
При входе и при выходе из параллельной секции директивы parallel
При выходе из параллельной секции директивы for
При выходе из параллельной секции директивы sections
При выходе из параллельной секции директивы single
При входе и при выходе из параллельной секции директивы parallel for
При входе и при выходе из параллельной секции директивы parallel sections
Поэтому дополнительно ее вызывать не надо!


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

Ошибки производительности (программа работает корректно, но неэффективно)Лишняя директива flushДиректива выполняется по умолчанию:В директиве barrierПри входе и при

Слайд 23Использование critical вместо atomic
Директива atomic работает быстрее, чем critical, поскольку

некоторые атомарные операции могут быть напрямую заменены командами процессора.
?директиву

желательно применять для защиты общей памяти при элементарных операциях:
x binop= expr
x++
++x
x--
--x
binop: +, *, -, /, &, ^, |, <<, или >>.

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

Использование critical вместо atomicДиректива atomic работает быстрее, чем critical, поскольку некоторые атомарные операции могут быть напрямую заменены

Слайд 24Лишняя защита от одновременной записи
Любая защита памяти от одновременной записи

(atomic, critical) замедляет выполнение программы.
?Без необходимости эту защиту лучше

не использовать.
Переменную не нужно защищать от одновременной записи если она:
является локальной для треда;
участвует в выражении firstprivate, private или lastprivate;
участвует в коде, который гарантированно выполняется только одним тредом – в параллельной секции директивы master или директивы single.

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

Лишняя защита от одновременной записиЛюбая защита памяти от одновременной записи (atomic, critical) замедляет выполнение программы. ?Без необходимости

Слайд 25Злоупотребление критическими секциями
Из-за критических секций треды ждут друг друга, что

уменьшает приращение производительности за счет распараллеливания.
На вход в критические

секции и на выход из них также тратится время.
?Не надо ими злоупотреблять.

? В критические секции не рекомендуется помещать:
вызовы сложных функций (нужна их декомпозиция),
код, не работающий с общими переменными, объектами или ресурсами.

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

Злоупотребление критическими секциямиИз-за критических секций треды ждут друг друга, что уменьшает приращение производительности за счет распараллеливания. На

Слайд 26Пример – сокращение входов в критические секции
Неэффективно:
#pragma omp parallel for


for ( i = 0 ; i < N; ++i

)
{
#pragma omp critical
{
if (arr[i] > max)
max = arr[i];
}
}

Эффективно :
#pragma omp parallel for
for ( i = 0 ; i < N; ++i )
{
#pragma omp flush(max)
if (arr[i] > max)
{
#pragma omp critical
{
if (arr[i] > max)
max = arr[i];
}
}
}

Если вынести условие из критической секции, вход в нее будет производиться далеко не во всех итерациях цикла.

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

Пример – сокращение входов в критические секцииНеэффективно:#pragma omp parallel for 	for ( i = 0 ; i

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика