10

I'm creating a basic prime number checker, based on C - determine if a number is prime , but utilising 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;
}

When compiling with -fopenmp, GCC version 4.7.2 is erroring, stating invalid controlling predicate with respect to the for loop.

It looks like this error is caused by the j squared in the for loop. Is there a way I can work around this and still achieve the desired output from the algorithm?

Community
  • 1
  • 1
Nick
  • 1,554
  • 1
  • 10
  • 27
  • are you sure that return statement is allowed in an open mp loop construct ? – alexbuisson Jul 10 '13 at 16:03
  • Unfortunately, parallelizing the loop with OpenMP is not going to help for testing for a single prime with trial division. You can, however, use it effectively for testing for multiple primes using trial division. However, for finding lists of primes I recommend the Sieve of Eratosthenes. Here is a version using OpenMP http://create.stephan-brumme.com/eratosthenes/ – Z boson Jul 12 '13 at 09:07
  • Also, in your `isPrime` function I recommend using `j <= j/value` instead of `j*j <= value` which can overflow http://rosettacode.org/wiki/Primality_by_trial_division#C – Z boson Jul 12 '13 at 09:09

2 Answers2

14

return is not allowed inside the loop as it will cause exit before the curly braces.

Note the definition given below :

From the OpenMP V2.5 spec, 1.2.2 OpenMP language terminology, p2:17-

structured block - For C/C++, an executable statement, possibly compound, with a single entry at the top and a single exit at the bottom.

A structured block starts with the open { and ends with the closing }. The return is contained within these braces, so this program also violates the OpenMP definition for a structured block, because it has two exits (one at the return and one at the exit through the brace)

OpenMP places the following five restrictions on which loops can be threaded:

  • The loop variable must be of type signed integer. Unsigned integers, such as DWORD's, will not work.
  • The comparison operation must be in the form loop_variable <, <=, >, or >= loop_invariant_integer
  • The third expression or increment portion of the for loop must be either integer addition or integer subtraction and by a loop invariant value.
  • If the comparison operation is < or <=, the loop variable must increment on every iteration, and conversely, if the comparison operation is > or >=, the loop variable must decrement on every iteration.
  • The loop must be a basic block, meaning no jumps from the inside of the loop to the outside are permitted with the exception of the exit statement, which terminates the whole application. If the statements goto or break are used, they must jump within the loop, not outside it. The same goes for exception handling; exceptions must be caught within the loop.
0decimal0
  • 3,884
  • 2
  • 24
  • 39
  • 1
    I don't understand why the loop variable must be signed. What if you need an integer greater than a signed 8 byte number? – Nubcake Jul 19 '17 at 13:12
6

According to the OpenMP standard (§2.5.1, p.40), the acceptable forms of the controlling predicate of the for loop are:

  • var relational-op b, and
  • b relational-op var

Your use of j * j <= value is a clear violation of this requirement. The rationale is that it requires the compiler to emit code that computes the integer square root of value at run time, with the latter being undefined for some values of value, specifically for the negative ones.

You can replace j * j <= value with j <= sqrt_value, where sqrt_value is the integer square root of value, but then would come the problem with having an alternative exit path in the structured block inside the loop. Unfortunately no easy solution exists in this case since OpenMP does not support premature termination of parallel loops.

Hristo Iliev
  • 72,659
  • 12
  • 135
  • 186