3

I have the following program:

int main(){
   double sum=0;
   #pragma omp parallel for reduction(+:sum)
   for(double x=0;x<10;x+=0.1)
   sum+=x*x;
}

When I compile it, I get the error invalid type for iteration variable ‘x’.

I take this to mean that I can only apply a parallel for construct to integer-based loops. But the internals of my loop really do depend on it being floating-point.

Is there a way to convince OpenMP to do this? Is there a recommended alternative method?

Richard
  • 56,349
  • 34
  • 180
  • 251
  • 2
    No, for the same reasons as in the answer given [here](http://stackoverflow.com/a/13403626/463827); even if it might work in some cases in general it's not extremely difficult for the compiler to reason about floating point numbers in the way needed to break up the loop. (Even purely serial optimization/vectorization of this loop would suffer for the same reason). Make an equivalent integer loop and calculate your float; `for (int i=0; i<100; i++) { double x=0.1*i; sum += x*x; }` – Jonathan Dursi Jan 19 '13 at 22:55
  • @JonathanDursi, if you write this up as an answer, I will accept it. – Richard Jan 21 '13 at 12:49
  • Ok, thanks, I've done that below. – Jonathan Dursi Jan 21 '13 at 13:51

3 Answers3

7

From comments:

No, OpenMP won't do this for you for the same reasons as in this answer given to a question about OpenMP loops with integer arithmetic; it's extremely difficult for the compiler to reason about floating point numbers - in particular, the compiler needs to know before entering the loop the loop's tripcount, and floating point arithmetic in the loop makes that very difficult in general, even if there are some simple cases that would be ok (say, looping by 0.5 to 10.0).

For the same reason, even purely serial optimization/vectorization of loops of this form would suffer. The best way to do it is to make an equivalent integer loop and calculate your float based on the integer index;

for (int i=0; i<100; i++) { 
    double x=0.1*i; 
    sum += x*x; 
}
Community
  • 1
  • 1
Jonathan Dursi
  • 50,107
  • 9
  • 127
  • 158
0

More generally, you need to go and read What Every Computer Scientist Should Know About Floating-Point Arithmetic. The fact that you're adding 0.1 and expecting precise results suggest that you haven't read it yet :-)

Jim Cownie
  • 2,409
  • 1
  • 11
  • 20
  • I have read it. I hope there's nothing about my question which implies I am expecting exact results. I am not. Naturally the code displayed in the question is only a MWE for a more complicated piece of code for which an exact result is not necessary. – Richard Jan 21 '13 at 01:23
  • 1
    @Richard, actually there is something about your question which implies that you (indirectly through what you tell the compiler) are expecting an exact result of a kind. OpenMP parallel loops only work if the number of loop trips can be precomputed exactly. `0.1` is an infinite-length binary fraction and hence the trip count might get computed differently given different FPU conditions. – Hristo Iliev Jan 21 '13 at 11:29
  • Fair enough, @HristoIliev. Ultimately, I'll probably end up down-voting the current version of your answer because it does not, I feel, really attempt to answer the question. It would, however, be appropriate as a comment. I mention this in case you do have thoughts that answer the question. – Richard Jan 21 '13 at 12:50
  • @Richard, it's a comment, not an attempt to answer. Jonathan Dursi has already done a very nice job in doing so. – Hristo Iliev Jan 21 '13 at 15:19
0

OpenMP standard defines "for" loop only for integer, pointer and iterator types, not for floating point types:

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

2.7.1 Loop Construct

  #pragma omp for [clause[ [,] clause] ... ] new-line
  for-loops

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

2.6 Canonical Loop Form

A loop has canonical loop form if it conforms to the following:

for (init-expr; test-expr; incr-expr) structured-block

init-expr One of the following:

 var = lb
 integer-type var = lb
 random-access-iterator-type var = lb
 pointer-type var = lb

...

incr-expr One of the following:

++var
var++
-- var
var --
var += incr
var -= incr
var = var + incr
var = incr + var
var = var - incr

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.

The canonical form allows the iteration count of all associated loops to be computed before executing the outermost loop

So, for non-canonical types compiler can't compute iteration counts.

osgx
  • 90,338
  • 53
  • 357
  • 513