For the first time, I tried to use threads by myself in order to implement a parallel sieve of Eratosthenes. The trick is that each time a prime is found, a thread is spawned to eliminate all the multiples of this prime number from the boolean vector (the one that tells whether a number is a prime or not). Here is my code:
#include <cmath>
#include <functional>
#include <thread>
#include <vector>
// Invalidates the multiples of the given integer
// in a given boolen vector
template<typename Integer>
void apply_prime(Integer prime, std::vector<bool>& vec)
{
for (Integer i = prime*2u ; i < vec.size() ; i += prime)
{
vec[i] = false;
}
}
template<typename Integer>
auto sieve_eratosthenes(Integer n)
-> std::vector<Integer>
{
std::vector<bool> is_prime(n, true);
std::vector<std::thread> threads;
std::vector<Integer> res;
auto end = static_cast<Integer>(std::sqrt(n));
for (Integer i = 2u ; i <= end ; ++i)
{
// When a prime is found,
// * add it to the res vector
// * spawn a thread to invalidate multiples
if (is_prime[i])
{
res.push_back(i);
threads.emplace_back(apply_prime<Integer>,
i, std::ref(is_prime));
}
}
for (auto& thr: threads)
{
thr.join();
}
// Add the remaining primes to the res vector
for (Integer i = end+1u ; i < is_prime.size() ; ++i)
{
if (is_prime[i])
{
res.push_back(i);
}
}
return res;
}
The primes are added in two steps to the res
vector: every prime \$ p \$ such as \$ p < \sqrt{n} \$ is added when the prime is found, before the corresponding thread is thrown. The other primes are added at the end the of the function. Here is an example main
:
int main()
{
auto primes = sieve_eratosthenes(1000u);
for (auto prime: primes)
{
std::cout << prime << " ";
}
}
I was pretty sure that I would get some problems due to parallelism, but for some reason, it seems to work. I got the expected results in the right order. Just to be sure, I would like to know whether my program is or correct or whether it has some threading issues that I couldn't see.
Note: I used many of the ideas from the answer to improve the code and wrote a follow-up question.