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 的行为。例如,它什么时候必须做很少的工作?)

为什么使用 2 个线程没有加速? 为什么相对于线程数的加速不是单调的? (提示:注意 4 和 6 线程时的行为。)

老实说,我不知道这是什么原因。我知道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 语言编写一个程序,该程序使用递归来确定一个数字是不是为素数。大量出现堆栈溢出错误

Pthreads 与 OpenMP

如果共享堆栈或数据变量,OpenMP 是不是会将它们移动到堆中?

是否有一个简单的算法可以确定 X 是否为素数?

ECC