OpenMP:确定它们是不是是素数
Posted
技术标签:
【中文标题】OpenMP:确定它们是不是是素数【英文标题】:OpenMP: decide if they are prime numbersOpenMP:确定它们是否是素数 【发布时间】:2019-11-05 09:40:34 【问题描述】:请注意,这是一个基于思考的问题。 给定的代码尝试测试某个范围(10,000,000)以内的数字是否为素数。
bool test_prime(int x)
if (x == 0)
return false;
int lim = (int) sqrt((double) x);
for (int i = 2; i <= lim; i++)
if (x % i == 0)
return false;
return true;
#pragma omp parallel for schedule(static)
for (int t = 0; t < nthreads; t++)
tf(t, nthreads, xmax, isprime);
线程函数有两种类型tf
:
void thread_run_interleave(int t, int nthreads, int xmax, bool *isprime)
for (int x = t; x <= xmax; x += nthreads)
isprime[x] = test_prime(x);
void thread_run_chunk(int t, int nthreads, int xmax, bool *isprime)
int npt = (xmax + nthreads - 1)/nthreads;
int xstart = npt*t;
int xlast = t == nthreads-1 ? xmax : xstart + npt - 1;
for (int x = xstart; x <= xlast; x++)
isprime[x] = test_prime(x);
加速如下:
-
2 个线程:交错 1.04,块 1.62
3 个线程:交错 1.93,块 2.17
4 个线程:交错 1.92,块 2.74
5 个线程:交错 3.53,块 3.08
6 个线程:交错 1.93,块 3.86
第一个问题要求解释thread_run_interleave
的加速。 (注:回答这个问题需要
思考test_prime
的行为。例如,它什么时候必须做很少的工作?)
老实说,我不知道这是什么原因。我知道test_prime
在输入 x
很小的情况下几乎没有什么作用,而对于较大的值却有很多作用。
【问题讨论】:
请为您的问题创建一个minimal reproducible example,并添加详细的硬件描述以及有关如何编译代码的信息。 好吧,我只是想出了 2 线程的原因。线程 0 获得所有偶数,因此它们都不是素数,它们可以被 2 整除并快速退出 test_prime。另一方面,线程 1 必须测试更长的时间,因为它具有所有质数。这种工作负载不平衡导致 1 个线程运行大部分工作,因此在速度方面接近串行。 @Zulan 这实际上是一个书面作业问题,所以没有代码。 @KcAble 你可以自己写答案并接受它。 这里有几个 Q 和 As 来解决这个问题中提出的问题。例如,请参阅***.com/questions/15463046 【参考方案1】:根据您正在测试的硬件,您可能会在函数thread_run_interleave
中遇到错误共享,因为您正在写入isprime[x]
,并且在每个线程中x
的值可能相似(取决于这些线程将被安排在 cpu 上)。这可以解释使用更多线程时速度变慢的原因。
这可以通过在每个线程中处理一小块连续数字来解决。
假设您的高速缓存行是 64B 宽,那么您将在每个线程中处理 64/sizeof(bool) 个连续数字,然后将 x
移动 (64/sizeof(bool))*nthreads (假设 isprime
是一个布尔数组)。
【讨论】:
以上是关于OpenMP:确定它们是不是是素数的主要内容,如果未能解决你的问题,请参考以下文章
用 C 语言编写一个程序,该程序使用递归来确定一个数字是不是为素数。大量出现堆栈溢出错误