1
votes

I am trying to parallelize a "for loop" of my C/OpenMP code, after offload call on Intel MIC (Xeon Phi) card. I am using "#pragma omp parallel for" and it compiles good when I use an integer variable as "loop control variable". On my code I am using a float array as "loop control variable" and then I get the error "parallel loop condition does not test loop control variable".

Code with no error:

#define MAX_DIMENSIONS  10

unsigned long long  i,y=0;

#pragma offload target(mic) in(i,y)
{
    #pragma omp parallel for
    for(i=0;i<10;i++)
        /* code here */  
}

Code with error:

#define MAX_DIMENSIONS  10

float   x[MAX_DIMENSIONS];
unsigned long long  i,y=0;

#pragma offload target(mic) in(x[MAX_DIMENSIONS],i,y)
{
    #pragma omp parallel for
    for(x[0]=0.000000; x[0]<10.000000; x[0]+=1.000000)
        /* code here */
}

Is there any way to keep that float array notation in "for loop" in order to succeed the parallelization using OpenMP?

2

2 Answers

4
votes

OpenMP requires loop variable to be of integer type:

http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=68

The syntax of the loop construct is as follows:

#pragma omp for  ...
 for-loops

...

Specifically, all associated for-loops must have canonical loop form (see Section 2.6 on page 53).

3 The iteration count for each associated loop is computed before entry to the outermost loop. If execution of any associated loop changes any of the values used to compute any of the iteration counts, then the behavior is unspecified.

6 The integer type (or kind, for Fortran) used to compute the iteration count for the collapsed loop is implementation defined.

You can't use variables of floating type in openmp loop construction. Your first loop has i integer which is correct and second has float typed variable which is incorrect. Canonical loop form is defined in "2.6 Canonical Loop Form" - http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=62 as

for (init-expr; test-expr; incr-expr) structured-block
...
var - One of the following:
* A variable of a signed or unsigned integer type.
* For C++, a variable of a random access iterator type.
* For C, a variable of a pointer type

incr-expr One of the following:
 ...
* var += incr

 incr A loop invariant integer expression

and your second loop has not canonical form and can't be paralleled.

#pragma omp parallel for
for(x[0]=0.000000; x[0]<10.000000; x[0]+=1.000000)

It will be hard to compiler to get loop iteration count in advance with floating point values of var and incr: some decimal constants can't be represented exactly in floating point format (for example, 0.2 in floating point is 0f3FC999999999999A; and 0.1 + 0.2 is 0.30000000000000004 in many languages, check https://0.30000000000000004.com/).

You can try array of integers or longs or long longs:

#define MAX_DIMENSIONS  10

long long  x[MAX_DIMENSIONS];
unsigned int i,y=0;

#pragma offload target(mic) in(x[MAX_DIMENSIONS],i,y)
{
    #pragma omp parallel for
    for(x[0]=0; x[0] < 10; x[0] += 1)
        /* code here */
}

Or you can try to estimate correct loop count for floating point range before loop and then use integer iterators in parallel loop as var and incr (be sure to do correct rounding).

2
votes

You can implement the working sharing manually like this

#pragma omp parallel
{
    float a = 0., b = 10.;
    float step = 1.;
    int N = (b-a)/step;
    int ithread = omp_get_thread_num();
    int nthreads = omp_get_num_threads();
    float t0 = (ithread+0)*N/nthreads + a;
    float t1 = (ithread+1)*N/nthreads + a;
    for(float x=t0; x<t1; x += step) {
      //code
    }
}

This would be equivalent to

#pragma omp parallel for 
for(float x=a; x<b; x += step)

if the omp for construct supported floating point iterators. For other schedules such as dynamic you have to implement them differently. Note that it's possible the parallel code and then sequential code don't give the same result e.g. if (b-a)/step has a fractional part (but (10.-0)/1. = 10. is okay). Therefore it's probably best to change your code to use integer iterators to be safe.