Understanding max and min in OpenACC reduction

Hi!

This is what I did to find the max integer in an array.

int value = INT_MIN;
#pragma acc parallel loop independent\
        deviceptr(arr) copy(value) reduction(max:value)
for (int i = 0; i < n; ++i) {
   int a = arr[i];
   // value = max(a, value);
   value = std::max(a, value);
}
return value;

Obviously, I can’t use max because it’s not defined in C++ and I suppose I should not use fmax instead. This observation confused me – how are these two max (one in the pragma line, one in the loop) related? It never occurred to me when I coded in Fortran.

If the compiler doesn’t care about what function we use to set value inside the loop, would the following code be correct?

int value;
#pragma acc parallel loop independent\
        deviceptr(arr) copyout(value) reduction(max:value)
for (int i = 0; i < n; ++i) {
   value = arr[i];
}
return value;

Thanks.
stw

Hi stw,

No, the code would not be correct. If you compiled the code without OpenACC, you’d get incorrect results. The reduction clause is there to instruct the compiler to add the necessary code to perform the reduction in parallel, such as the creation of the partial reduction array of “value” (one for each vector in this case) and add the final reduction kernel after the for loop.

Note for NVHPC, we can often detect reductions and implicitly add the “reduction” clause for you. It might be why you didn’t need to add it in your Fortran codes. Though technically it’s required by the OpenACC standard and other compilers, such as GNU, may not support implicit reductions.

Obviously, I can’t use max because it’s not defined in C++ and I suppose I should not use fmax instead.

This is incorrect. C is a subset of C++ so any C routine can be used in C++, assuming the appropriate header file is included. Though using “std::max” is fine as well.

-Mat

1 Like