i am using OpenMP reduction(min) to get the minimum number of lock acquisitions in a parallel section over all participating threads. When printing each threads counter inside the parallel section, I get correct results but after the parallel section, the min counter is at 0. This is the code:
int counter = 0, maxV, minV;
bool _continue = true; //variable to indicate when one second is over
#pragma omp parallel private(id) shared(lock, _continue) reduction(min:minV) reduction(+:counter) reduction(max:maxV)
{
id = omp_get_thread_num();
if(id == 0)
{
auto start = std::chrono::high_resolution_clock::now(); //start time measurement
while(_continue)
{
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::micro> elapsed = finish - start;
if(elapsed.count() > std::chrono::microseconds(sec).count())
{
_continue = false;
}
}
}
else
{
while(_continue) //during timeframe, try to obtain lock as often as possible
{
lock.lock(id);
lock.unlock(id);
counter++;
}
minV = counter;
maxV = counter;
}
#pragma omp critical
{
std::cout << id << ": " << minV << std::endl;
}
}
std::cout << minV << std::endl;
The typical output is something like:
0: 2147483647
7: 256985
4: 255973
1: 256975
6: 255740
5: 256658
3: 256856
2: 256943
0
So even for thread 0, the thread that is not acquiring the lock but just taking the time, the minV is correctly initialized as largest representable number in the reduction list item type (int).
Depending on what compiler options I choose, I can alter the result of minV (last line in cout) to the following values (always wrong...):
minV = 32767 | -std=c++14 -fopenmp
minV = 0 | -std=c++14 -fopenmp -O3
minV = 32766 | -std=c++14 -fopenmp -Wall
minV = 32767 | -std=c++14 -fopenmp -Wall -pedantic -march=native -fconcepts
So I assume it has something to do with my compiler options? Strangely though, the max and sum reduction appear to work fine...
Any help is appreciated.
You have a confusion between the init value that OMP uses internally, and the init value from the user code. The partial reductions are done with the internal value, but at some point there also has to be a reduction against the user-supplied initial value. If you don't set that, anything can happen.
Here is a cute picture: https://theartofhpc.com/pcse/omp-reduction.html#Initialvalueforreductions