I'm writing a program to count prime numbers from 2 to N using OpenMP. I wrote this code and while testing it, for example, with N = 10 (OMP_NUM_THREADS=2 ./main 10) I get mostly 4-s but sometimes I get 5-s in my output. It seems like there is a race condition that I cannot see and I don't now where it is. Can you help me to find this condition and get rid of it?
#include <iostream>
#include <omp.h>
#include <vector>
int main(int argc, char *argv[])
{
if (argc != 2)
return -1;
const unsigned long N = std::atoi(argv[1]);
unsigned counter = 0;
std::vector<bool> numbers(N + 1, true);
numbers[0] = numbers[1] = false;
#pragma omp parallel shared(numbers, counter)
{
#pragma omp single
{
for (size_t i = 2; i * i <= N; ++i)
{
if (numbers[i] == true)
#pragma omp task
{
for (size_t j = i * i; j <= N; j += i)
numbers[j] = false;
}
}
#pragma omp taskwait
}
#pragma omp for reduction(+ \
: counter)
for (size_t i = 1; i <= N; ++i)
if (numbers[i] == true)
counter++;
}
std::cout << counter << std::endl;
return 0;
}
Edit: appreciate all the help in the comments. Calling sanitizer really helped to detect a data race condition. Adding "#pragma for critical" for the numbers[j]=false
does solve the problem with multiple writings and dealing with race conditions.
But this works only for big numbers N, when we have multiple false
writes in same position.
So I want to return previous question to particular case with N=10:
here are no multiple writings in same region, take a look at cycles:
(size_t i = 2; i * i <= N; ++i)
will give us i = 2,3. So with for (size_t j = i * i; j <= N; j += i)
we will have j = 4,6,8,10,9.
After this I took a look at the output "numbers" vector, and in case where my program returns "5" there is this array: 0 0 1 1 0 1 0 1 0 1 0
where bits represent numbers from 0 to 10 from left to right and prime numbers marked as "1"-s.
I think, it's impossible for the main "single" thread execute earlier than threads, called by "task" directive because I have #pragma omp taskwait
. If that is true, then I don't know why I have such strange output. How do you think, what causes the problem here?