Неявный барьер против Nowait в случае двух последовательных прагма omp для - PullRequest
0 голосов
/ 13 ноября 2018

Глядя на документ здесь , следующая конструкция хорошо определена:

#pragma omp parallel          //Line 1
{
#pragma omp for nowait        //Line 3
  for (i=0; i<N; i++)
    a[i] = // some expression
#pragma omp for               //Line 6
  for (i=0; i<N; i++)
    b[i] = ...... a[i] ......
}

, поскольку

Здесь предложение nowait подразумевает, что потоки могут запускатьсяво втором цикле, в то время как другие потоки все еще работают над первым.Поскольку оба цикла используют здесь одно и то же расписание, итерация, использующая [i], может действительно полагаться на то, что это значение было вычислено.

Мне трудно понять, почему это так.Предположим, что Line 3 были:

#pragma omp for

тогда, так как непосредственно перед Line 6 существует неявный барьер, следующий цикл for будет иметь значения при всех индексах a полностьювычислен.Но с no wait в Line 3 как это будет работать?

Предположим, Line 1 запускает 4 потока, t1, t2, t3 и t4.Предположим, что N равно 8, а разбиение индексов в первом цикле for таково:

t1: 0, 4
t2: 1, 5
t3: 2, 6
t4: 3, 7

Предположим, t1 сначала завершает индексы 0 и 4 и получает Line 6 Чтоточно сейчас происходит?Как гарантируется, что теперь он будет работать с теми же индексами 0 и 4, для которых значения a правильно вычислены им на предыдущей итерации?Что если второй for цикл обращается к a[i+1]?

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Для меня утверждение о том, что в этом примере нет потенциальной проблемы, неверно.

Действительно, планирование будет таким же, как оно не определено явно. Это будет по умолчанию. Кроме того, если бы планирование было типа static, то действительно, не было бы никакой проблемы, поскольку поток, который обрабатывал бы любые данные в массиве a внутри второго цикла, был бы таким же, как тот, который имел бы записал это в первом цикле.

Но настоящая проблема здесь в том, что планирование по умолчанию не определено стандартом OpenMP. Это определяется реализацией ... Для (многих) реализаций, где планирование по умолчанию равно static, во фрагменте не может быть никаких условий гонки. Но если расписание по умолчанию равно dynamic, то, как вы заметили, может возникнуть условие гонки и результат не определен.

0 голосов
/ 13 ноября 2018

Материал, который вы цитируете, неверен.Это станет правильным, если вы добавите schedule(static) к обоим циклам - это гарантирует одинаковое распределение индексов между потоками для последовательных циклов.Расписание по умолчанию определяется реализацией, вы не можете считать его static.Чтобы процитировать стандарт:

Различные области цикла с одинаковым расписанием и количеством итераций, даже если они встречаются в одной параллельной области, могут распределять итерации по потокам по-разному.Единственным исключением является статическое расписание, указанное в таблице 2.5.Программы, которые зависят от того, какой поток выполняет конкретную итерацию при любых других обстоятельствах, не соответствуют требованиям.

Если второй доступ к циклу a[i+1], вы должны абсолютно оставить там барьер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...