Почему это?= оператор не разрешен с OpenMP?


Я пытался скомпилировать следующий код:

#pragma omp parallel shared (j)
{
   #pragma omp for schedule(dynamic)
   for(i = 0; i != j; i++)
   {
    // do something
   }
}

Я получаю эту ошибку: ошибка: недопустимый управляющий предикат.

Я проверяю openMP справочник и он говорит, что для параллели для него "только" позволяет один из следующих операторов: >=.

Я не понимаю, почему не разрешить i != j. Я мог бы понять, если бы это было статическое расписание, так как openMP нужно предварительно вычислить количество итераций назначается каждому потоку. Но я не могу понять, почему это ограничение в таком случае, например. Какие-нибудь улики ?


редактировать: даже если я сделаю for(i = 0; i != 100; i++), хотя я мог бы просто поставить "

5 66

5 ответов:

.

я отправил электронное письмо разработчикам OpenMP по этому вопросу, ответ я получил:

для подписанного int поведение обертывания не определено. Если мы позволим !=, программисты могут получить неожиданный tripcount. Проблема заключается в том, может ли компилятор генерировать код для вычисления количества поездок для цикла.

для простого цикла, например:

for( i = 0; i < n; ++i )

компилятор может определить, что есть' n ' итераций,если n>=0, и нулевые итерации если n .

для цикла типа:

for( i = 0; i != n; ++i ) 

опять же, компилятор должен быть в состоянии определить, что есть' n ' итераций,если n >= 0;если n , мы не знаем, сколько итераций он.

для цикла типа:

for( i = 0; i < n; i += 2 )

компилятор может генерировать код для вычисления количества поездок (количество итераций цикла) как этаж ((n+1) / 2) если n >= 0, и 0 если n .

для цикла типа:

for( i = 0; i != n; i += 2 )

компилятор не может определить, будет ли 'i' когда-либо ударить 'n'. Что, если 'n' - нечетное число?

для цикла типа:

for( i = 0; i < n; i += k )

компилятор может генерировать код для вычисления количества поездку, как пол ((n+k-1)/k) если n >= 0 и 0 если n , потому что компилятор знает, что цикл должен подсчитывать; в этом случае, если k , это не правовой Программа OpenMP.

для цикла типа:

for( i = 0; i != n; i += k )

компилятор даже не знает, считаю ли я вверх или вниз. Он не знает, попаду ли я когда-нибудь в "Н". Это может быть бесконечный цикл.

кредиты: OpenMP ARB

вопреки тому, как это может выглядеть,schedule(dynamic) не работает с динамическим числом элементов. Скорее назначение итерационных блоков потокам-это то, что является динамическим. При статическом планировании это назначение предварительно вычисляется в начале конструкции worksharing. При динамическом планировании итерационные блоки выдаются потокам в порядке очереди.

стандарт OpenMP довольно ясно, что количество итератонов предварительно вычисляется после workshare конструкция встречается, поэтому счетчик циклов не может быть изменен внутри тела цикла (спецификация OpenMP 3.1, §2.5.1-Loop Construct):

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

целочисленный тип (или вид, для Fortran), используемый для вычисления количество итераций для свернутый цикл определяется реализацией.

цикл совместной работы и логической итерации нумеруются 0,1,...,N-1, где n-число циклические итерации, а логическая нумерация обозначает последовательность, в которой выполняются итерации будет выполняться, если связанные циклы были выполнены одним потоком. Этот schedule предложение указывает, как итерации связанных циклов делятся на непрерывные непустые подмножества, называемые кусками, и как они куски распределяются между потоками рабочей группы. Каждый поток выполняет свой назначенный кусок (ы) в контексте его неявная задача. Элемент chunk_size выражение вычисляется с использованием исходных элементов списка любых переменных, которые становятся частными в конструкции цикла. Не определено, происходят ли, в каком порядке или сколько раз какие-либо побочные эффекты оценки этого выражения. Использование переменной в schedule выражение предложения конструкции цикла вызывает неявное ссылка на переменную во всех вложенных конструкциях.

обоснование этих ограничений реляционных операторов довольно простое-оно обеспечивает четкое указание на то, что такое направление цикла, оно позволяет легко вычислять количество итераций, и оно обеспечивает аналогичную семантику директивы worksharing OpenMP в C/C++ и Fortran. Также другие реляционные операции потребовали бы тщательной проверки тела цикла, чтобы понять, как идет цикл что во многих случаях было бы неприемлемо и сделало бы реализацию громоздкой.

OpenMP 3.0 представил явное task конструкция, которая позволяет распараллеливать петли с неизвестным числом итераций. Однако есть уловка: задачи вводят некоторые серьезные накладные расходы, и одна задача на итерацию цикла имеет смысл только в том случае, если эти итерации занимают довольно много времени. В противном случае накладные расходы будут доминировать во время выполнения.

ответ прост. OpenMP не допускает преждевременного завершения команды потоков. С = = или != , OpenMP не имеет возможности определить, когда цикл останавливается. 1. Один или несколько потоков могут попасть в условие завершения, которое может быть не уникальным. 2. OpenMP не имеет возможности отключить другие потоки, которые могут никогда не обнаружить условие.

если бы я увидел заявление

for(i = 0; i != j; i++)

используется вместо оператора

for(i = 0; i < j; i++)

мне было бы интересно почему программист сделал этот выбор, не обращая внимания на то, что это может означать то же самое. Возможно, OpenMP делает жесткий синтаксический выбор, чтобы добиться определенной ясности кода.

вот код, который вызывает проблемы для использования != и может помочь объяснить, почему это не допустимый.

#include <cstdio>

int main(){
    int j=10;
   #pragma omp parallel for
   for(int i = 0; i < j; i++){
    printf("%d\n",i++);
   }
}

заметил, что i увеличивается в обоих for заявление, а также внутри самого цикла, что приводит к возможности (но не гарантии) бесконечного цикла.

если предикат < тогда поведение цикла все еще может быть четко определено в параллельном контексте без необходимости компилятора проверять в цикле изменения в i и определение того, как эти изменения повлияют на границы цикла.

если предикат - это != тогда поведение цикла больше не является четко определенным, и оно может быть бесконечным по протяженности, предотвращая легкое параллельное подразделение.

Я думаю, что, возможно, нет никакой веской причины, кроме расширения существующей функциональности, чтобы получить это далеко.

IIRC первоначально они должны были быть статическими, чтобы он мог определить во время компиляции, как генерировать код цикла... это может быть просто похмелье от этого.