假设我有一个名为run()
的函数的程序,这个函数会执行for loop
并在其中做一些工作。
由于我想利用我的所有CPU核心,因此我使用OpenMP
与#pragma omp parallel for
进行并行化。
现在,问题是这个run()
函数是从几个线程调用的,当有大量线程同时调用run()
时,我有一个巨大的性能损失,因为那里每个OpenMP threads
pragma调用都会有很多parallel for
。
只是为了ilustrate,我有线程A
和线程B
,我的CPU有4个内核,线程A
调用函数run()
,它将创建4 OpenMP
线程运行for loop
。
现在,同时,线程B
也调用run()
,这将生成更多4 OpenMP
个线程,从而产生总共8个OpenMP
个线程。 / p>
我的问题是,如果有某种方法可以与OpenMP
进行平衡,在上面的示例中,OpenMP
可以使用A
的半个线程和B
的一半。
另一个策略是OpenMP
创建一个线程队列,因此它永远不会使用超过4个OpenMP
个线程。
这样的事情可能吗?
PS。请注意,我的示例中的2个线程只是为了说明它,在我的程序中不清楚将调用多少线程run()
,因为线程数是在运行时根据需要创建的。
PS 2.请注意,每当我谈论OpenMP
创建的线程时,我都称它为OpenMP
线程,当我谈论通过其他方式创建的线程时(例如std::thread
我简单地称它为线程。
答案 0 :(得分:0)
如果仅使用OpenMP进行并行操作,并且启用了nested parallelism,则可以使用num_threads
的{{1}}参数指定使用一半的线程:
pragma omp parallel
即使您使用混合线程技术(这似乎是您的情况),您仍然可以通过使用不同的方法设置int const currentNumThreads = omp_get_num_threads();
int const maxNumThreads = omp_get_max_num_threads();
#pragma omp parallel for num_threads(maxNumThreads/currentNumThreads)
for ( ... ) {
...
}
和currentNumThreads
来实现相同的目标。
但要谨慎。对于OpenMP,使用嵌套并行性通常是不可取的,因为它使代码非常fragile and rigid。对maxNumThreads
函数的任何更改都需要知道调用它的位置,并且将来对run()
的任何调用都需要了解其中的内容。在性能和维护方面,尝试遵循data parallel方法进行OpenMP使用是最好的。也就是说,在每个线程中执行一组类似的操作,但是在不同的数据块上执行。
例外情况是,如果您正在使用可以生成的OpenMP任务,并让调度程序处理它。在并行for循环中使用任务并行性将导致性能不佳,因为缺少data locality并且如果任务很小则开销很高。