Синхронизация типа flush
Поскольку в современных параллельных вычислительных системах может использоваться сложная структура и иерархия памяти, пользователь должен иметь гарантии того, что в необходимые ему моменты времени каждая нить будет видеть единый согласованный образ памяти. Именно для этих целей и предназначена директива flush.
Директива используется для обновления значений локальных переменных, перечисленных в качестве аргументов, в оперативной памяти. Выполнение данной директивы предполагает, что значения всех переменных, временно хранящиеся в регистрах, будут занесены в основную память, все изменения переменных, сделанные нитями во время их работы, станут видимы остальным нитям, если какая-то информация хранится в буферах вывода, то буферы будут сброшены и т.п.
Без ее использования, например, если один поток установил значение доступной обоим потокам общей переменной а, равное 1, это не гарантирует, что другой поток, обратившись к той же переменной, получит значение 1.
Формат:
#pragma omp flush(var1, [var2, […, varN ]])Здесь var1, var2, …, varN - список переменных, значения которых сохраняются в оперативной памяти в момент выполнения директории flush.
Поскольку выполнение данной директивы в полном объеме может повлечь значительных накладных расходов, а в данный момент нужна гарантия согласованного представления не всех, а лишь отдельных переменных, то эти переменные явно перечисляются в директиве списком.
Пример программы, иллюстрирующий использование синхронизации типа flush, приведен ниже. Если в данном примере отменить использование директивы – будет выведено значение 1.
#include "stdafx.h"
#include "omp.h"
#include "stdio.h"
#include <stdlib.h>
#include <iostream>
using namespace System;
using namespace std;
…
void TestFlush()
{
int a = 0;
#pragma omp parallel num_threads(10)
{
a++;
#pragma omp single
{
#pragma omp flush(a)
cout << a << endl;
}
}
Согласно спецификации директива flush присутствует неявно в следующих ситуациях:
- В директиве barrier
- При входе и при выходе из параллельной секции директивы critical
- При входе и при выходе из параллельной секции директивы ordered
- При входе и при выходе из параллельной секции директивы parallel
- При выходе из параллельной секции директивы for
- При выходе из параллельной секции директивы sections
- При выходе из параллельной секции директивы single
- При входе и при выходе из параллельной секции директивы parallel for
- При входе и при выходе из параллельной секции директивы parallel sections
Следовательно, явное использование flush в этих случаях будет лишним. Лишняя директива flush, особенно если соответствующие переменные не будут указаны в качестве параметров директивы (в этом случае делается синхронизация всей общей памяти), может существенно замедлить выполнение программы.
Директива flush не выполняется в следующих случаях:
- При входе в параллельную секцию директивы for.
- При входе и при выходе из секции директивы master.
- При входе в параллельную секцию директивы sections.
- При входе в секцию директивы single.
- При выходе из секции директивы for, single или sections, если к директиве применено выражение nowait (вместе с неявным барьером эта директива убирает и неявную директиву flush).
Дата добавления: 2015-02-03; просмотров: 852;