ошибка компилятора "недопустимый управляющий предикат" с использованием OpenMP
Я создаю базовую проверку простых чисел, основанную на C-определить, является ли число простым, но с использованием OpenMP.
int isPrime(int value)
{
omp_set_num_threads(4);
#pragma omp parallel for
for( int j = 2; j * j <= value; j++)
{
if ( value % j == 0) return 0;
}
return value;
}
при компиляции с -fopenmp, GCC версии 4.7.2 ошибается, заявив invalid controlling predicate
относительно цикла for.
похоже, что эта ошибка вызвана квадратом j в цикле for. Есть ли способ обойти это и все же достичь желаемого результата от алгоритма?
2 ответов
return
Не допускается внутри цикла, так как это приведет к выходу перед фигурными скобками.
обратите внимание на определение, приведенное ниже:
из OpenMP V2.5 spec, 1.2.2 терминология языка OpenMP, p2: 17-
structured block-Для C / C++, исполняемый оператор, возможно состав, с одиночным входом вверху и одиночным выходом на дно.
структурированный блок начинается с {
и заканчивается с закрытием }
. The return
содержится в этих фигурных скобках, поэтому эта программа также нарушает определение OpenMP для структурированного блока, потому что у него есть два выхода (один в return
и один на выходе через бандажа)
OpenMP устанавливает следующие пять ограничений, на которые могут быть продеты петли:
- переменная цикла должна иметь тип signed integer. Целое без знака, такие, как DWORD, не будут работать.
- сравнение операция должна быть в виде loop_variable
<
,<=
,>
, или>=
loop_invariant_integer - третье выражение или часть инкремента цикла for должны быть целочисленное сложение или целочисленное вычитание и цикл инвариантное значение.
- если операция сравнения
<
или<=
, переменная цикла должна инкремент на каждой итерации, и наоборот, если сравнение операция>
или>=
, переменная цикла должна уменьшаться на каждом итерация. - цикл должен быть базовым блоком, что означает отсутствие прыжков изнутри петля наружу разрешена, за исключением выхода заявление, которое завершает все приложение. Если заявления goto или перерыв используются, они должны прыгать внутри петли, а не снаружи он. То же самое касается обработки исключений; исключения должны быть пойманы внутри цикла.
в соответствии со стандартом OpenMP (§2.5.1, стр. 40), приемлемые формы управляющего предиката for
петли:
- var relational-op b и
- b реляционный-op var
использование j * j <= value
является явным нарушением этого требования. Обоснование заключается в том, что компилятор должен выдавать код, который вычисляет целочисленный квадратный корень из value
во время выполнения, которые не определено для некоторых значений value
специально для отрицательных.
вы можете заменить j * j <= value
С j <= sqrt_value
, где sqrt_value
- целочисленный квадратный корень из value
, но тогда возникнет проблема с альтернативным путем выхода в структурированном блоке внутри цикла. К сожалению, в этом случае нет простого решения, поскольку OpenMP не поддерживает преждевременное завершение параллельных циклов.