【发布时间】: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 来解决这个问题中提出的问题。例如,请参阅stackoverflow.com/questions/15463046
标签: c++ multithreading openmp