Discussion about Clang OpenMP Worksharing-Loop Linear clause finalization bug or unclear description in OpenMP standard?

Hi,

The value exiting the loop of the linear clause list-item seems not correct in clang openmp codegen. According to OpenMP 4.5 standard Section 2.15.3.7, the value corresponding to the sequentially last iteration of the associated loop(s) is assigned to the original list item.

Let’s look at the following test case:


#include<iostream>

using namespace std;

int main() {

int b = 10, M = 10;

int a[10], i;

#pragma omp parallel num_threads(4)

#pragma omp for linear(b: 2)

for (i = 0; i < M; i++)

a[i] = b;

cout << b << endl;

for (i = 0; i < M; i++)

cout << a[i] << " ";

cout << endl;

return 0;

}

The result of clang++ temp.cpp -fopenmp && ./a.out is

30

10 12 14 16 18 20 22 24 26 28

If we change the above test case as follows

#pragma omp parallel num_threads(4)

#pragma omp for linear(b: 2)

for (i = 0; i < M; i++) {

a[i] = b;

b = 10;

}

The result is the same. The exiting value in clang openmp codegen is implemented as (logical last iteration + 1) * linear_step + linear_base, which is (M – 1 + 1) * 2 + 10 for this case. This is apparently incorrect.

Here, there are two problems regarding to the Openmp standard.

  1. The example linear_in_loop.1.c in openmp-examples-5.1.pdf is as follows:

j = 0;

#pragma omp parallel

#pragma omp for linear(j:1)

for ( i = 0; i < N; i += 2 ) {

b[j] = a[i] * 2.0f;

j++;

}

j++ is really not necessary here. The compiler will calculate the j for each iteration according to the openmp standard (the value of the new list item on each iteration of the associated loop(s) corresponds to the value of the original list item before entering the construct plus the logical number of the iteration times linear-step) and j++ do the redundant calculation, which is not efficient.

  1. Which value should be assigned to the original list item?

If it is the value of the new list item after entering the construct, the results for the above two cases should be 28, 28. In this case, the value of “(M – 1) * linear_step + original_b” is assigned to the original b, where “M – 1” is the logical last iteration.

If it is the value of the new list item corresponding to the sequentially last iteration of the loop before exiting the construct, the results for the above two cases should be 28, 10. In this case, the value of the privatized variable b is assigned the the original b.

All the best,

Peixin