Паралельні нотатки N4 – продовжуємо знайомитися з конструкціями OpenMP
Продовжимо знайомство з технологією OpenMP та розглянемо деякі функції та нові директиви.
У OpenMP існує низка допоміжних функцій. Для їх використання не забудьте підключити заголовний файл.
Функції виконуючого середовища
Ці функції дозволяють запитувати та задавати різні параметри середовища OpenMP:
Якщо ім'я функції починається з omp_set_, її можна викликати лише поза паралельними регіонів. Всі інші функції можна використовувати як всередині паралельних регіонів, так і поза ними.
Функції синхронізації/блокування
OpenMP дозволяє будувати паралельний код без використання цих функцій, оскільки є директиви, що дозволяють здійснювати певні види синхронізації. Однак у ряді випадків ці функції зручні та навіть необхідні.
У OpenMP два типи блокувань: прості та вкладені. Вкладені мають суфікс "nest". Блокування можуть бути в одному з трьох станів - неініціалізованому, заблокованому та розблокованому.
- omp_init_lock/omp_init_nest_lock – ініціалізація змінної типу omp_lock_t/omp_nest_lock_t. Аналог InitializeCriticalSection.
- omp_destroy_lock/omp_destroy_nest_lock - звільнення змінної типу omp_lock_t/omp_nest_lock_t. Аналог DeleteCriticalSection.
- omp_set_lock/omp_set_nest_lock - один потік виставляє блокування, інші потоки чекають, поки потік, що викликала цю функцію, не зніме блокування з допомогою функції omp_unset_lock(). Аналог EnterCriticalSection.
- omp_unset_lock/omp_unset_nest_lock – зняття блокування. Аналог LeaveCriticalSection.
- omp_test_lock/omp_test_nest_lock – неблокуюча спроба захоплення замка. Ця функція намагається захопити зазначений замок. Якщо це вдалося, то для простого замку функція 1 повертає.Замок захопити не вдалося, то повертається 0. Аналог TryEnterCriticalSection.
Прості блокування (omp_lock_t) не можуть бути встановлені більше одного разу, навіть тим самим потоком. Блокування, що вкладаються (omp_nest_lock_t) ідентичні простим з тим винятком, що коли потік намагається встановити вже належне йому вкладається блокування, він не блокується.
Наведемо приклад коду, який використовує описані функції. Всі потоки по черзі виведуть повідомлення "Begin work" і "End work". Між цими двома повідомленнями від одного потоку можуть зустрітися повідомлення з інших потоків, що виводяться при невдалій спробі увійти до закритої секції.
На машині з чотирма ядрами може бути отриманий такий висновок: