在我的主要功能中,我设置了:
omp_set_num_threads(20);
告诉OpenMP使用20个线程(有40个线程可用)。
然后我执行包含指令的代码:
#pragma omp parallel for shared(x,y,z)
用于主循环,并通过htop监视CPU使用率(可能不是最好的方法,但仍然)。有50个任务" for循环必须执行,每次都需要很长时间。我通过htop观察到的是,在任务完成后,线程数会下降。具体来说,使用20个线程,我希望看到2000%的CPU使用率,直到剩下少于20个任务,之后线程应该是#34; free"他们自己。然而,我所看到的是2000%,在n个任务完成后,我看到2000% - (n * 100%)的表现。因此,当任务完成时,线程似乎关闭而不是接收新任务。
这是预期还是听起来很奇怪?
答案 0 :(得分:1)
几乎所有现有OpenMP编译器的默认并行循环调度都是static
,这意味着OpenMP运行时将尝试在线程之间均匀地分割迭代空间并执行静态工作分配。由于你有50个迭代和20个线程,所以工作不能被平分,因为20不会除以50.因此,一半的线程将进行三次迭代,而另一半将进行两次迭代。
在(组合parallel
)for
结构的末尾有一个隐式屏障,其中先前完成的线程等待其余线程完成。根据OpenMP实现,屏障可能实现为忙等待循环,某些OS同步对象上的等待操作,或两者的组合。在后两种情况下,击中屏障的线程的CPU使用率会在进入可中断睡眠状态时立即降至零,或者最初将在短时间内保持在100%(忙碌循环),然后降至零(等待)。
如果循环迭代花费的时间完全相同,那么最初的CPU使用率将是2000%,然后在两次迭代之后(如果屏障实现使用短忙循环则会更多)降至1000%。如果迭代每次花费不同的时间,那么线程将在屏障的不同时刻到达,CPU使用率将逐渐降低。
在任何情况下,使用schedule(dynamic)
让第一个线程的每次迭代都可用。在迭代花费不同时间的情况下,这将提高CPU利用率。当迭代每次花费相同的时间时,它将无济于事。后一种情况下的解决方案是将迭代次数作为线程数的整数倍。