Синхронизация типа 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; просмотров: 774;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.005 сек.