OpenMP实现并行埃拉托斯特尼筛法特定线程数下输出错误
问题原因
- 核心错误是
UPPER_BOUND宏的运算逻辑错误:宏定义中提前对n/N做整数除法截断,再乘以(p+1),而非先计算(p+1)*n再做整数除法,导致当线程数N无法整除输入规模n时,相邻线程的负责区间之间会出现未被任何线程覆盖的缝隙。 - 缝隙内的数字既不会被标记为合数,也不会被纳入最终的素数统计,若缝隙中存在素数,就会导致最终统计结果偏小。
- 测试中2、4、8、16等2的幂线程数结果正确,是因为你使用的测试用例
n(10000、100000、1000000)均为2的幂的倍数,整除场景下提前截断不会产生误差;而6、12、14无法整除n,就会出现缝隙导致结果错误。
修复方案
首先修正两个宏的运算逻辑,消除提前截断问题,同时为了避免宏展开的运算符优先级问题,给所有参数加上括号,冗余的尾线程判断也可以直接删掉:
#define LOWER_BOUND(p, N, n) ((p) == 0 ? 2 : (((p) * (n)) / (N))) #define UPPER_BOUND(p, N, n) ((((p) + 1) * (n)) / (N) - 1)
可选优化点(不影响正确性,仅提升性能)
- 避免每次找到素数都重新创建并行区域,可将
omp parallel提到外层循环外,减少线程同步开销 - 对
sqrt(n)的结果做边界校验,避免double转整数的精度误差导致漏筛大素数的倍数
内容的提问来源于stack exchange,提问作者KoalaBear
相关产品推荐
相关产品推荐

