S. Kaczor
S. Kaczor

Reputation: 401

Openmp with more than INT_MAX iterations - is it legal?

Here is a loop that works perfectly fine:

#include <inttypes.h>
#include <iostream>
int main() {
  for (int32_t i = -2; i < INT32_MAX-2; i++) {
    std::cout << i << std::endl;
  }
}

Adding omp parallel for clause seems to break the code by introducing int overflow.

#include <inttypes.h>
#include <iostream>
int main() {
  #pragma omp parallel for
  for (int32_t i = -2; i < INT32_MAX; i++) {
    std::cout << i << std::endl;
  }
}

For both clang-10 and gcc-10 the program produces no output. clang-12 on the other hand seems to handle it properly.

clang-10 at least produces some warnings:

> clang++-10 int_div.cpp -Wall -fopenmp
int_div.cpp:133:3: warning: overflow in expression; result is -2147483647 with type 'int' [-Winteger-overflow]
  for (int i = -2; i < INT32_MAX; i++) {
  ^
int_div.cpp:133:3: warning: overflow in expression; result is 2147483646 with type 'int' [-Winteger-overflow]
int_div.cpp:133:3: warning: overflow in expression; result is -2147483647 with type 'int' [-Winteger-overflow]
int_div.cpp:133:3: warning: overflow in expression; result is -2147483647 with type 'int' [-Winteger-overflow]
int_div.cpp:133:3: warning: overflow in expression; result is -2147483647 with type 'int' [-Winteger-overflow]

Is this a legal, well defined behavior of openmp standard or an implementation bug?

Upvotes: 1

Views: 148

Answers (4)

tstanisl
tstanisl

Reputation: 14157

It's not a bug in a compiler but rather unspecified behavior in OpenMP. See 2.9.1 Canonical Loop Form

If var is of an integer type, then the type is the type of var.

...

The behavior is unspecified if any intermediate result required to compute the iteration count cannot be represented in the type determined above.

A similar wording can be found on Microsoft site at 241-for-construct:

This computation is made with values in the type of var, after integral promotions. In particular, if value of b - lb + incr can't be represented in that type, the result is indeterminate.

Therefore the computation is done in int resulting in integer overflow thus UB.

Upvotes: 1

Laci
Laci

Reputation: 2818

The OpenMP standard does not contain anything about overflow of loop variable(s), so I think it is the programmer's responsibility to make sure it will not happen. Note that it can happen easily if the collapse clause is used (e.g. see this example).

Upvotes: 0

Victor Eijkhout
Victor Eijkhout

Reputation: 5810

OpenMP loops need to compute the number of iterations before starting the loop, so the type of the loop variable needs to be such that the number is expressible. Other than that, the OMP standard allows both signed and unsigned integer types, with no restriction indicated.

Upvotes: 0

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38773

#pragma omp parallel for would result in the execution flow with omp_get_num_threads() for loop count, something like:

for (int32_t i = -2; i < INT32_MAX; i += omp_get_num_threads())
  std::cout << i << std::endl;

for (int32_t i = -1; i < INT32_MAX; i += omp_get_num_threads())
  std::cout << i << std::endl;

// ...

for (int32_t i = -2 + omp_get_thread_num() - 1; i < INT32_MAX; i += omp_get_num_threads())
  std::cout << i << std::endl;

The second and further threads would result in signed integer overflow.

Upvotes: 0

Related Questions