Организация параллельных потоков. Часть 2 | страница 14



%%i.


Ключ /L позволяет указать диапазон значений счётчика и шаг изменения.

Далее мы указываем диапазон значений — от единицы до десяти с единичным шагом:

(1, 1, 10).

Тело цикла — наша команда — запуск программы на выполнение.

Запускаем пакетный файл (рис. 4.10).

Результаты нас устраивают.

Последовательное выполнение программы не даёт ошибок в расчётах.


Рис. 4.10. Цикл в пакетном файле


Задание. Создайте пакетный файл (рис. 4.10) и запустите его.


Теперь запустим несколько потоков.

Установим три потока:

set OMP_NUM_THREADS=3.

Запускаем пакетный файл.

Получаем десять разных результатов (рис. 4.11).

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


Рис. 4.11. Результаты гонки


Задание. Запустите пакетный файл, задавая разное количество параллельных потоков. Обратите внимание на ошибки в расчётах.

4.2.2. Редукция

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

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

Английское слово REDUCTION в данном конкретном случае означает «сворачивание, собирание, соединение, объединение, сведение».

Мы будем использовать параметр reduction в директиве pragma:

#pragma omp parallel for reduction (+: S).

Эта конструкция позволяет автоматически организовать параллельные вычисление и сбор частичных сумм.

Знак [+] указывает, что будет найдена сумма (есть и другие операции).

S — переменная, с которой будем работать.

Составляем программу (рис. 4.12).

При входе в параллельную область в каждом потоке создаётся локальная копия переменной S. Это механизм напоминает создание локальной переменной внутри подпрограммы. Из других модулей к локальной переменной доступа нет.

Слово ЛОКАЛЬНЫЙ буквально означает «местный, внутренний».


Рис. 4.12. Редукция


Создаём пакетный файл, аналогичный рассмотренному.

Переходим в командное окно и задаём разное количество параллельных потоков.

Запускаем пакетный файл.

Смотрим на результаты (рис. 4.13).

Последовательный запуск даёт правильные результаты.


Рис. 4.13. Последовательный запуск


Задаём несколько потоков.

Запуск тоже даёт правильные результаты (рис. 4.14).