Хелпикс

Главная

Контакты

Случайная статья





Семинар 10. Тема: Технология OpenМР: работа с общими и локальными данными



Семинар 10

Тема: Технология OpenМР: работа с общими и локальными данными

                      

По итогам прошлого семинара – знаем, что в OpenMP-программе работу начинает одна нить (нить-мастер), с помощью прагмы omp parallel организуются параллельные блоки, выполняемые набором потоков (нитей), количество которых можно регулировать, каждая из нитей имеет свой номер и нить-мастер имеет номер 0.

Взаимосвязь между нитями в параллельных секциях, а также между параллельными (многопоточными) и последовательными (однопоточными) участками кода поддерживается за счет различных типов данных.

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

В OpenMP определены следующие основные типы переменных, характеризующие доступ к ним из разных участков OpenMP-программы (эти типы объявляются в прагмах parallel; не путать со стандартными типами данных int, float и т.п.):

· shared – такие переменные являются общими для всех нитей, т.е. все нити во всех параллельных и последовательных областях кода будут обращаться одной области памяти;

· private – каждый поток имеет свою копию переменной, значение которой обновляется независимо каждой нитью, не передается из последовательной области параллельную и не сохраняется за пределами параллельной области;

· firstprivate – аналогична private, но переменные данного типа при входе в параллельный регион инициализируются значением, которое переменная имела перед открытием этого региона;

· lastprivate - аналогична private, но после закрытия параллельной области переменные сохраняют значение, полученное в ходе вычислений внутри параллельного региона. Используется в конструкциях for и section.

На кластере HybriLIT типом переменной по умолчанию является shared.

В таблице показано, как ведут себя переменные типа shared, private, firstprivate при переходе из последовательной области в параллельную и обратно.

OpenMP-тип переменной private firstprivate shared
Начальное значение a, заданное в мастер-нити int a=199; int a=199; int a=199;
Значение а в каждой нити сразу после входа в параллельную область а=0 а=199 а=199
Изменение значения а в параллельной области

int id=omp_get_thread_num;

a+=id;

Значение а в каждой нити перед выходом из параллельной области a=id a=id+199 может меняться от запуска к запуску
Значение а в мастер-нити после выхода из параллельной области а=199 а=199 может меняться от запуска к запуску

 

 

Пример 1:

Задаем целочисленную переменную а – private, значение которой, как в таблице, задается в начале программы, когда работает только одна нить, нить-мастер.

Пусть a =199, как в таблице.

Выводим на дисплей значения этой переменной:

- в мастер-нити;

- в начале параллельной секции,

- в конце параллельной секции после некоторых вычислений;

- после закрытия параллельной секции.

Будем следить – как изменится (или не изменится) значение а.

Что наблюдаем при запуске этой программы (интерактивный запуск с числом нитей 6 по умолчанию):

Пример 2:

Объявим теперь в нашем предыдущем примере переменную а – firstprivate:

#pragma omp parallel firstprivate(a)

Снова проследим, как будет меняться (или не изменится) ее значения при открытии и закрытии параллельной области.

Видно, что при входе в параллельную область в каждой из шести нитей переменная а имеет значение а=199, заданное в мастер-нити до открытия паралельной области. Далее, каждая нить вычисляет свое собственное значение а, равное ее номеру, и выводит это значение на печать. Однако после закрытия параллельной области результаты этих расчетов не сохраняются. По-прежнему имеем в мастер-нити а=199, как и в предыдущем примере.

 

Пример 3:

Теперь пусть наша переменная а –  общая (shared):

#pragma omp parallel shared(a)

Снова проследим, как будет меняться (или не изменится) ее значение при открытии и закрытии параллельной области.

Поскольку переменная общая и все нити в параллелньой области имеют к ней равноправный доступ – при входе в паралельную область каждая нить печатает а=199, далее каждая нить увеличивает значение общей для всех переменной на величину, равную своему номеру, так что на печати наблюдаем постепенное увеличение значения а. После закрытия параллельной области имеем: а=199+0+1+2+3+4+5 = 214.

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

Из-за этого финальное значение переменной а может меняться от запуска к запуску. Для того, чтобы убедиться в этом – запустим программу несколько раз подряд:

 

 

Видно, что в разных запусках финальное значение а – разное: вместо а=199 может получаться а=212, а=210 и т.п.

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

 

Таким образом, работа с общими данными требует внимательности и аккуратности. «Разруливать» ситуации, подобные представленной в примере 3, помогают директивы синхронизации нитей и опция редукции, которые будем изучать на следующих семинарах.

 

Задание

 

1. Изучить раздел 2.1 учебного пособия по OpenMP.

2. Воспроизвести на кластере Hybrilit вышеприведенные примеры по работе с локальными и общими данными, убедившись, что объясненные выше закономерности поведения соответствующих переменных сохраняются.

3. Составить и запустить программу, выполняющую следующее. В мастер-нити объявляются целочисленные переменные a=1, b=10, c=100. Пусть c – private, b – shared, a – firstprivate. Пусть в параллельной области производятся следующие действия: c=a+id; b+=a; а=22. Нужно вывести на печать значения a, b, c после закрытия параллельной области и объяснить полученный результат.

 

 



  

© helpiks.su При использовании или копировании материалов прямая ссылка на сайт обязательна.