嵌套的 openmp 循环

Nested openmp loop

本文关键字:循环 openmp 嵌套      更新时间:2023-10-16

我有一段以下风格的代码:

for (set=0; set < n; set++)  //For1
{
   #pragma omp parallel for num_threads(x)
    for (i=0; i < m; i++)   //For2: this loop can be executed in parallel
   {
      commands...
   }
   for (j=0; j < m; j++)   //For3: this loop depends on the output of the For2 and also should be executed in a sequential way
   {
     commands...
   }
}

正如你所注意到的,我有 n 个独立的集合(外循环,即 For1)。每个集合由一个并行循环 (For2) 和一个顺序部分 (For3) 组成,它们应该在 For2 之后执行。

我已经在 For2 中使用了 num_threads(x)#pragma omp 并行"以使其并行。

现在我也想使外循环 (For1) 平行。换句话说,我想并行运行每个 Set。

如果您能让我知道在 openmp 中是如何实现的,我真的很感激。

一种方法可能是创建对应于每个 Set 的 n 个线程。 正确吗?但是我想知道是否还有另一种完全使用 openmp 功能的方法?

提前谢谢。

您可以简单地并行外部循环

#pragma omp parallel for num_threads(x) private(i,j)
for (set=0; set < n; set++)  //For1
{
    for (i=0; i < m; i++)   //For2: this loop can be executed in parallel
   {
      commands...
   }
   for (j=0; j < m; j++)   //For3: this loop depends on the output of the For2 and also should be executed in a sequential way
   {
     commands...
   }
}

您可以尝试融合第一个和第二个循环(见下文)。 我不知道这是否会让它变得更好,但值得一试。

    #pragma omp parallel num_threads(x) private(set, i)
    {
        #pragma omp for schedule(static)
        for (k = 0; k < n*m; k++) //fused For1 and For2
        {
            set = k/m;
            i = k%m;
            //commands...
        }
        #pragma omp for schedule(static)
        for (set = 0; set < n; set++)
        {
            for (i = 0; i < m; i++) //For3 - j is not necessary so reuse i 
            {
                //commands...
            }
        }
    }

简单地并行化外部循环可能是您的最佳选择,具体取决于您拥有的集合数量。如果计算机上的内核数超过内核数,则可能比并行化内部循环更快,因为在这种情况下,线程创建开销要少得多。

假设您的操作受 CPU 限制,并且外部循环并行化,您将充分利用计算机上的所有内核。如果所有资源都已使用,则进一步尝试并行化内部循环不会更快。

如果您的

集少于可用内核,请并行化内部循环,您很可能已经消耗了所有可用的计算能力。

如果你真的想并行化两个循环,那么你应该考虑MPI并在多台计算机上进行混合并行化;外部循环在多台计算机上并行化,内部循环在一台计算机的所有内核上并行化。