- •Типичные ошибки
- •Логические ошибки
- •• Пропущено omp
- •• Пропущено for
- •• Лишнее parallel
- •• Пропущено ordered
- ••Переопределение количества тредов внутри параллельной секции
- •• Зависимость поведения программы от числа тредов
- •Вывод алфавита Некорректно:
- ••Некорректное динамическое создание тредов
- •Вывод алфавита Корректно:
- ••Одновременное использование общего ресурса
- ••Незащищенный доступ к общей памяти
- •Некорректно:
- ••Отсутствие директивы flush Директива flush неявно не выполняется :
- •Некорректно:
- •• Отсутствие явной синхронизации тредов
- ••Не инициализированы локальные переменные
- ••Ограничения для локальных переменных Если требуется создать локальную копию объекта, массива или ссылочной
- •• Не определен порядок итераций цикла Некорректно:
- •Корректно:
- •Ошибки производительности
- •Использование critical вместо atomic
- •Лишняя защита от одновременной записи
- •Злоупотребление критическими секциями
- •Пример – сокращение входов в критические секции Неэффективно: Эффективно :
Типичные ошибки
по материалам статьи «32 подводных камня OpenMP при программировании на Си++»
http://software.intel.com/ru-ru/articles/32-openmp-traps-for-c-developers/
•Речь об ошибках, которые
не обнаруживаются компилятором.
•Выделяют логические ошибки и ошибки
производительности.
•Логические ошибки приводят к неожиданным результатам, то есть к некорректной работе программы.
•Ошибки производительности приводят к снижению быстродействия программы.
1
Лекция 9. Захарова И.Г., Кафедра ПО
Логические ошибки
• Не подключено
OpenMP
Корректно:
#pragma omp parallel for
• Пропущено parallel... // код
Некорректно:
#pragma omp for |
или |
... //код |
#pragma omp parallel |
|
{ |
|
#pragma omp for |
|
... //код |
|
} |
|
2 |
|
Лекция 9. Захарова И.Г., Кафедра ПО |
• Пропущено 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. Захарова И.Г., Кафедра ПО |
3 |
|
• Пропущено 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. Захарова И.Г., Кафедра ПО |
4 |
|
• Лишнее 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. Захарова И.Г., Кафедра ПО |
5 |
|
• Пропущено 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. Захарова И.Г., Кафедра ПО |
6 |
|
•Переопределение количества тредов внутри параллельной секции
Некорректно:
#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. Захарова И.Г., Кафедра ПО |
7 |
|
• Зависимость поведения программы от числа тредов
Число тредов:
•По умолчанию, как правило, равно числу установленных на компьютере процессоров.
•Может также задаваться программистом:
•функция omp_set_num_threads,
•опция num_threads,
•переменная среды OMP_NUM_THREADS.
•По умолчанию может оказаться разным на разных компьютерах.
•Если это специально не заложено в алгоритм, то поведение кода не должно зависеть от количества выполняющих его тредов.
•Распределение работы между тредами выполняет компилятор.
•Можно использовать опцию schedule.
Лекция 9. Захарова И.Г., Кафедра ПО |
8 |
Вывод алфавита Некорректно:
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);
}
Выведет только 24 буквыКорректно: omp_set_num_threads(4);
#pragma omp parallel for
for (int i = 'a'; i <= 'z'; i++)
{ printf ("%c", i); }
Лекция 9. Захарова И.Г., Кафедра ПО |
9 |
|
•Некорректное динамическое создание тредов
•Переменная среды bool OMP_DYNAMIC задает возможность динамического определения числа тредов.
•Переменная имеет больший приоритет, чем опция num_threads.
•Если выполнение кода зависит от количества выполняющих его тредов, поведение программы может стать некорректным.
•Спецификация OpenMP - значение OMP_DYNAMIC
зависит от конкретной реализации.
•Следовательно, необходимы доп. проверки.
Лекция 9. Захарова И.Г., Кафедра ПО |
10 |