- •Паралельнi цикли в OpenMp програмах
- •Синхронізація в OpenMp програмах
- •Директива omp single в OpenMp програмах
- •Директива omp master в OpenMp програмах
- •Директиви barrier та flush в OpenMp програмах
- •Паралельнi секцiї в OpenMp програмах
- •Методи задання кількості потоків в OpenMp програмах
- •Управлiння розподiлом iтерацiй циклу мiж потоками
- •Директива ordered та nowait в OpenMp програмах(там де опції)
- •Виконання паралельної областi за умовою та задання кількості потоків
- •Змiннi оточення та допомiжнi функцiї в OpenMp програмах
- •Управлiння розподiлом iтерацiй циклу OpenMp програмах. (8 питання)
- •Директива omp master в OpenMp програмах
- •Директива omp critical в OpenMp програмах
- •Написати приклад паралельного множення
- •Написати приклад використання критичних
- •Написати приклад використання синхронiзацiї
- •Написати приклад паралельного додавання
- •Написати приклад паралельного
Директива ordered та nowait в OpenMp програмах(там де опції)
Виконання паралельної областi за умовою та задання кількості потоків
Виконання паралельної областi за умовою та задання кількості потоків. Паралельна область задається за допомогою директиви parallel #pragma omp parallel [опцiя[ [, ]опцiя] ...] • if (умова) – виконання паралельної областi за умовою; • num_threads(цiлочисельний вираз) – явне завдання кiлькостi потокiв, якi будуть виконувати паралельну область; за замовчуванням вибирається останнє значення встановлене функцiєю omp_set_num_threads (), або значення змiнної оточення OMP_NUM_THREADS;
Змiннi оточення та допомiжнi функцiї в OpenMp програмах
OMP_NUM_THREADS – задання кiлькiсть потокiв, що виконують паралельну область. З програми її можна змiнити за допомогою виклику функцiї omp_set_num_threads(). У деяких випадках система може динамiчно змiнювати кiлькiсть потокiв, використовуваних для виконання паралельної областi, наприклад, для оптимiзацiї використання ресурсiв системи. Це дозволено робити, якщо змiнна середовища OMP_DYNAMIC встановлена в true. Змiнну OMP_DYNAMIC можна встановити за допомогою функцiї omp_set_dynamic(), дiзнатися значення змiнної можна за допомогою функцiї omp_get_dynamic().
Функцiя int omp_get_max_threads() повертає максимально кiлькiсть потокiв допустиму для використання в наступнiй паралельнiй областi.
Функцiя int omp_get_num_procs() повертає кiлькiсть процесорiв, доступних для використання програмою користувача на момент виклику.
Керувати вкладеним паралелiзмом можна установкою змiнної оточення OMP_NESTED (true, false), або функцiєю omp_set_nested().
Функцiя int omp_get_thread_num(); повертає номер потоку в паралельнiй областi, з якої була викликана.
Функцiя double omp_get_wtime() повертає, в потоцi котрий її викликав, астрономiчний час в секундах, що минув з деякого моменту в минулому.
Функцiя double omp_get_wtick() повертає роздiльну здатнiсть таймера в секундах.
Управлiння розподiлом iтерацiй циклу OpenMp програмах. (8 питання)
Директива omp master в OpenMp програмах
Директиви master видiляють дiлянку коду, який буде виконаний тiльки основним потоком. Решта потокiв просто пропускають дану дiлянку i продовжують роботу з оператора, розташованого слiдом за ним. Неявної синхронiзацiї дана директива не передбачає.
Директива omp critical в OpenMp програмах
Цей тип синхронізації використовується для опису структурних блоків, що виконуються тільки в одному потоці з усього набору паралельних потоків.
За допомогою директив #pragma omp critical [(<name>)] оформлюється критична секцiя програми. У кожний момент часу в критичнiй секцiї може перебувати не більше одного потоку. Якщо критична секцiя вже виконується будь-яким потоком, то всi інші потоки, якi виконали директиву для секцiї з даним name, будуть заблокованi, поки що увiйшов до критичної секцiї не закiнчить виконання. Як тiльки працюючий потiк вийде з критичної секцiї, один iз заблокованих на входi потокiв увiйде в неї. Якщо на входi в критичну секцiю стояло кiлька потокiв, то випадковим чином вибирається один з них, а iншi заблокованi потоки продовжують очiкування. Всi неiменованi критичнi секцiї умовно асоцiюються з одним i тим же iм’ям. Всi критичнi секцiї, що мають одне i теж iм’я, розглядаються єдиної секцiєю, навiть якщо знаходяться в рiзних паралельних областях. Побiчнi входи i виходи з критичної секції забороненi.
фрагмент iлюструє застосування директиви critical , змiнна n оголошена за межами паралельної областi, тому за замовчуванням є спiльною. Критична секція дозволяє розмежувати доступ до змiнної n. Кожен потiк по черзi присвоїть n свiй номер i потiм надрукує отримане значення.
int n ; #pragma omp parallel{
#pragma omp critical{
n=omp_get_thread_num( ) ;
printf ( "Потiк ␣%d\n" , n ) ;}}
Опції:
_ private(список) – задає список змiнних, для яких породжується локальна копiя в кожному потоцi; початкове значення локальних копiй змiнних зi списку не визначене;
_ firstprivate (список) – задає список змiнних, для яких породжується локальна копiя в кожному потоцi; локальнi копiї змiнних iнiцiалiзуются значеннями цих змiнних в основному потоцi;
_lastprivate (список) – змiнним, перерахованим у списку, присвоюється результат, отриманий в останнiй секцiї;
_ copyprivate(список) – пiсля виконання потоку, що мiстить конструкцiю single, новi значення змiнних списку будуть доступнi всiм однойменним приватним змiнним (private та firstprivate ), описаним на початку паралельної областi; опцiя не може використовуватися спiльно з опцiєю nowait; змiннi списку не повиннi бути перерахованi в опцiях private i firstprivate даної директиви single;
_reduction(оператор: список) – задає оператор i список спiльних змiнних; для кожної змiнної створюються локальнi копiї в кожному потоцi; локальнi копiї iнiцiалiзуются вiдповiдно до типу оператора (для адитивних операцiй – 0 або його аналоги, для мультиплiкативних операцiй – 1 або її аналоги); над локальними копiями змiнних пiсля виконання всiх операторiв паралельної областi виконується заданий оператор; оператори для мови Сi – +, ,_,&,|,^,&&,||,max,min; порядок виконання операторiв не визначений, тому результат може вiдрiзнятися вiд запуску до запуску.
_ nowait – пiсля виконання видiленої дiлянки вiдбувається неявна бар’єрна синхронiзацiя паралельно працюючих потокiв: їх подальше виконання вiдбувається тiльки тодi, коли всi вони досягнуть даної точки; якщо в подiбнiй затримцi немає необхiдностi, опцiя nowait дозволяє потокам, котрi вже дiйшли до кiнця дiлянки, продовжити виконання без синхронiзацiї з iншими.
_ordered – опцiя, що говорить про те, що в циклi можуть зустрiчатися директиви ordered; в цьому випадку визначається блок всерединi тiла циклу, який повинен виконуватися в тому порядку, в якому iтерацiї йдуть в послiдовному циклi;
Написати приклад обчислення сум по cтовпцях
матриці з використанням директиви reduction
#pragma omp parallel
{ #pragma for shared(x) private(i) reduction(+:sum)
{for ( i =0; i < NMAX; i++) {sum = 0 ;
for ( j=i ; j < NMAX; j++) sum = a [ j ] [ i ] ;}}}
Написати приклад обчислення сум по cтовпцях матриці
з використанням директив private shared
#pragma omp parallel for shared ( a ) pr i vat e ( i , j , sum) \
schedule ( dynamic , chunk ) ordered
{ for ( i =0; i < NMAX; i++) { sum = 0 ;
for ( j=i ; j < NMAX; j++)
sum += a [ j ] [ i ] ; #pragma omp ordered
p r i n t f ( "Сума елементів стовпця %d␣ р i в н а ␣%f \n" , i , sum) ; }}
Написати приклад обчислення сум матриць
з використанням директиви ordered
#include <omp.h>
int myval=0,i,n=10;
#pragma omp parallel for private(myval) ordered { for(i=1; i<=n; i++){ myval += i; #pragma omp ordered { printf("%d \n", myval); } }}
Написати приклад обрахунку суми двох
скінчених сум з використанням паралельних секцій
double sum1 = 0,sum2=0;
#pragma omp parallel private(sum1,sum2){
#pragma omp sections {
#pragma omp section{
for(i=1; i<=n; i++)
sum1 += i;
result+=sum1;}
#pragma omp section{
for(i=1; i<=m; i++)
sum2 += i;
result+=sum2;}}}
printf("x = %fl", result);
return 0;}
Написати приклад використання
директиви master (що виведе програма?)
#
Виведе:
[0]
= 0
[1]
= 1
[2]
= 4
[3]
= 9
[4]
= 16
#include <stdio.h>
int main( )
{ int a[5], i;
#pragma omp parallel
{ #pragma omp for
for (i = 0; i < 5; i++)
a[i] = i * i;
#pragma omp master
for (i = 0; i < 5; i++)
printf_s("a[%d] = %d\n", i, a[i]);
#pragma omp barrier
#pragma omp for
for (i = 0; i < 5; i++)
a[i] += i; }}
