使用崩溃子句是否更好

时间:2019-01-03 10:53:24

标签: c++11 openmp

我永远不确定应该选择哪种方式并行化嵌套的for循环。

例如,我有以下代码片段:

#pragma omp parallel for schedule(static)
for(int b=0; b<bSize; b++)
    for(int n=0; n<N; n++) o[n + b*N] = b[n];


#pragma omp parallel for collapse(2) schedule(static)
for(int b=0; b<bSize; b++)
    for(int n=0; n<N; n++) o[n + b*N] = b[n];

在第一个代码段中,我使用parallel for(由于使用了第一个触摸策略,因此使用schedule(static))。在某些代码中,我看到人们在其他代码中大多使用塌陷子句来嵌套嵌套的for循环,而从未使用过,而是使用简单的parallel for将嵌套的for循环并行化。这是更习惯还是两个版本之间有区别?某些人从不使用collapse(n)是有原因的吗?

1 个答案:

答案 0 :(得分:3)

与HPC中的所有内容一样,答案是“取决于...”

这取决于

  1. 您的计算机有多大,“ bSize”和“ N”有多大
  2. 内循环的内容是什么

对于所有在相同时间运行的迭代静态调度,除非可以保证工作共享的迭代数除以线程数,否则需要确保可用迭代数约为10倍由于潜在的不平衡,保证90%效率的线程数。因此,如果您有16核计算机,则需要> 160次迭代。如果“ bSize”很小,则使用折叠生成更多可用的并行性将有助于提高性能。 (在最坏的情况下,请想象“ bSize”小于线程数!)

另一方面,正如@ tim18指出的那样,如果您可以向量化内部循环,同时又保持足够的并行度,那可能是更好的选择。

另一方面,没有什么可以阻止您同时进行这两项工作:-

#pragma omp for simd collapse(2)
for(int b=0; b<bSize; b++)
    for(int n=0; n<N; n++) o[n + b*N] = b[n];

如果您的内部循环确实很小(并且可以向量化),那么您肯定要对其向量化,因为与并行性不同,向量化可以减少您使用的CPU总时间,而不仅仅是在内核之间移动。