Хелпикс

Главная

Контакты

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





Семинар 14. Тема семинара. Технология OpenМР: операция редукции. Пример 1.



Семинар 14

Тема семинара

Технология OpenМР: операция редукции

          

Как мы уже знаем, директива синхронизации critical обеспечивают корректную работу с общими переменными в случае, если требуется, чтобы каждая нить выполнила какую-либо операцию надо общими данными. Другой вариант организации корректной работы с общими данными – операции редукции.

Опция reduction прагмы parallel задаёт операцию редукции (сложение, умножение, и т.п.) и список переменных редукции, над которыми указанная операция производится.

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

 

Пример 1.

...

int nCount=10;

#pragma omp parallel reduction (+ : nCount)

{

...

nCount+=1;

...

}

...

 

В данном фрагменте целочисленная переменная nCount объявлена переменной редукции, а операцией редукции является сложение.

Если переменная объявлена переменной редукции – ее нельзя объявлять локальной или общей, это будет ошибкой. Логика работы с этой переменной следующая. При входе в параллельную область для каждой переменной редукции создаются локальные копии с тем же именем в каждой нити. Начальные значения этих локальных переменных в каждой нити определяются типом операции редукции и никак не связаны со значением переменной с этим именем до начала параллельной области. Так, для операции сложения начальное значение переменной редукции 0, для умножения – 1, см. таблицу в Приложении 4 Учебного пособия по OpenMP.

В нашем примере, поскольку операцией редукции является сложение, начальные значения локальных переменных nCount в каждой нити параллельной области равны 0, несмотря на то, что перед началом параллельной области мы имели nCount=10.

Итак, при входе в параллельную область каждая нить имеет начальное значение переменной редукции nCount=0. Далее, Каждая нить увеличивает свою переменную nCount на единицу, т.е. при закрытии параллельной области каждая нить имеет nCount=1.

При закрытии параллельной области над всеми переменным nCount из каждой нити осуществляется операция редукции (в нашем случае – сложение). Все переменные nCount=1 из всех нитей складываются между собой, и эта сумма прибавляется к тому значению nCount, которое эта переменная имела до объявления параллельной области, т.е. nCount=10.

Таким образом, после закрытия параллельной области будем иметь значение переменной nCount, равное 10+количество нитей, что мы и видим при запуске нижеследующего кода с количеством нитей, равным по умолчанию 6.

 

 

 

 

В необходимости использования опции редукции для корректной работы с общими переменными можно убедиться, если убрать эту опцию и задать достаточно большое количество нитей. В этой ситуации есть вероятность, что одна или более нитей обратится к общему для всех адресу nCount в момент, когда это значение еще не обновлено по результатам работы других нитей, так что результат окажется меньше, чем 10+количество нитей и может меняться от запуска к запуску. Это хорошо видно на скриншоте: при количестве нитей 40 при многократных запусках время от времени получаем nCount =49, nCount =47 и даже nCount =45 вместо nCount =50.

 

 

 



  

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