0

在我的主要功能中,我设置了:

omp_set_num_threads(20);

它告诉 OpenMP 使用 20 个线程(有 40 个线程可用)。

然后我执行包含指令的代码:

#pragma omp parallel for shared(x,y,z)

用于主 for 循环,并通过 htop 监控 CPU 使用情况(可能不是最好的方法,但仍然如此)。for 循环必须执行 50 个“任务”,每个都需要相当长的时间。我通过 htop 观察到,任务完成后,线程数下降。具体来说,使用 20 个线程,我希望看到 2000% 的 cpu 使用率,直到剩余的任务少于 20 个,之后线程应该“释放”自己。但是,我看到的是第一个 2000%,在 n 个任务完成后,我看到了 2000% - (n*100%) 的性能。因此,似乎随着任务完成,线程关闭而不是接收新任务。

这是意料之中的还是听起来很奇怪?

4

1 回答 1

1

几乎所有现有 OpenMP 编译器的默认并行循环调度是static,这意味着 OpenMP 运行时将尝试在线程之间平均划分迭代空间并执行静态工作分配。由于您有 50 次迭代和 20 个线程,因此无法平均分配工作,因为 20 不能除以 50。因此,一半的线程将执行 3 次迭代,而另一半将执行 2 次迭代。

parallel在 (combined )构造的末尾有一个隐式屏障,for其中较早完成的线程等待其余线程完成。根据 OpenMP 实现,屏障可能被实现为忙等待循环,作为对某些 OS 同步对象的等待操作,或作为两者的组合。在后两种情况下,遇到障碍的线程的 CPU 使用率要么在进入可中断睡眠时立即降至零,要么在短时间内保持 100%(忙碌循环),然后降至零(这段等待)。

如果循环迭代花费完全相同的时间,那么会发生的情况是 CPU 使用率最初为 2000%,然后在两次迭代之后(如果屏障实现使用短忙循环,则更多)将下降到 1000 %。如果每次迭代花费不同的时间,那么线程将在不同的时刻到达屏障,CPU 使用率将逐渐降低。

在任何情况下,使用schedule(dynamic)将每次迭代都分配给第一个线程以使其可用。在迭代花费不同时间的情况下,这将提高 CPU 利用率。当迭代每次花费相同的时间时,这将无济于事。后一种情况的解决方案是将迭代次数设为线程数的整数倍。

于 2016-05-04T19:44:44.103 回答