-
-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
One off error in C/CPP API libprimesieve multi-threading demonstrations #137
Comments
I tested both the C and C++ OpenMP sum primes examples using your Which version of primesieve are you using (use |
$ primesieve -v
primesieve 11.1, <https://github.com/kimwalisch/primesieve>
Copyright (C) 2010 - 2023 Kim Walisch
BSD 2-Clause License <https://opensource.org/licenses/BSD-2-Clause> The C and C++ OpenMP demonstrations |
Yes, you are right. I was able to reproduce the bug now. |
Great! For debugging the issue, I added the #include <primesieve.h>
#include <inttypes.h>
#include <stdio.h>
#include <omp.h>
int main(void)
{
uint64_t sum = 0;
uint64_t dist = 1e10;
int threads = omp_get_max_threads();
uint64_t thread_dist = (dist / threads) + 1;
#pragma omp parallel for ordered reduction(+: sum)
for (int i = 0; i < threads; i++)
{
uint64_t start = i * thread_dist + 1;
uint64_t stop = start + thread_dist < dist ? start + thread_dist : dist;
#pragma omp ordered
printf("start = %ld, stop = %ld\n", start, stop);
primesieve_iterator it;
primesieve_init(&it);
primesieve_jump_to(&it, start, stop);
uint64_t prime = primesieve_next_prime(&it);
/* Sum primes inside [start, stop] */
for (; prime <= stop; prime = primesieve_next_prime(&it))
sum += 1;
}
printf("Count of the primes <= 10^10: %" PRIu64 "\n", sum);
return 0;
} |
Notice the 1-off error. The first segment has a stop value ending in 3. And the 2nd segment has a starting value ending in 3 as well. It just happens that the 1-off error doesn't manifest itself running with 1 to 9 threads.
Fix:
|
The cleanest fix I have come up so far is: #pragma omp parallel for reduction(+: sum)
for (int i = 0; i < threads; i++)
{
uint64_t start = i * thread_dist;
uint64_t stop = start + thread_dist;
stop = stop < dist + 1 ? stop : dist + 1;
primesieve_iterator it;
primesieve_init(&it);
primesieve_jump_to(&it, start, stop);
uint64_t prime = primesieve_next_prime(&it);
/* Sum primes inside [start, stop[ */
for (; prime < stop; prime = primesieve_next_prime(&it))
sum += 1;
} I removed |
The output is correct, but not seeing unique starting and stopping values. Here, the segment 1 stopping value is the same as the segment 2 starting value. $ OMP_NUM_THREADS=10 ./primesum2
start = 0, stop = 1000000001
start = 1000000001, stop = 2000000002
start = 2000000002, stop = 3000000003
start = 3000000003, stop = 4000000004
start = 4000000004, stop = 5000000005
start = 5000000005, stop = 6000000006
start = 6000000006, stop = 7000000007
start = 7000000007, stop = 8000000008
start = 8000000008, stop = 9000000009
start = 9000000009, stop = 10000000001
Count of the primes <= 10^10: 455052511 |
Is this really an issue? The stop number is simply non-inclusive as mentioned in the comment: I also tried to find a fix with an inclusive stop number, but the code is not as clean and requires more |
I came across your GitHub repo and read through the C/CPP documentation. And tried the OpenMP demonstrations. I changed it to counting
sum += 1
(experimenting) and noticed the count was incorrect, not matching theprimesieve
utility.C API libprimesieve multi-threading example
CPP API libprimesieve multi-threading example
The 1-off error is caused by the following line. I was getting the correct/wrong output depending on the number of threads specified.
Fix: Subtract 1 e.g.
start + thread_dist - 1
.The text was updated successfully, but these errors were encountered: