OpenMP - 仅创建一次线程



我尝试使用OpenMP编写简单的应用程序。不幸的是,我在加速方面遇到了问题。在这个应用程序中,我有一个while循环。此循环的主体由一些应按顺序完成的指令和一个 for 循环组成。我使用 #pragma omp parallel for 来使它用于循环并行。这个循环没有太多工作,但经常被调用。

我准备了两个版本的 for loop,并在 1、2 和 4 核上运行应用程序。
版本 1(for 循环中的 4 次迭代):22 秒、23 秒、26 秒。
版本 2(for 循环中的 100000 次迭代):20 秒、10 秒、6 秒。

如您所见,当 for 循环没有太多工作时,2 核和 4 核上的时间比 1 核上的时间长。我想原因是#pragma omp parallel for在 while 循环的每次迭代中都会创建新线程。所以,我想问你 - 是否有可能创建一次线程(在 while 循环之前),并确保 while 循环中的某些工作将按顺序完成?

#include <omp.h>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(int argc, char* argv[])
{
    double sum = 0;
    while (true)
    {
        // ...
        // some work which should be done sequentially
        // ...
        #pragma omp parallel for num_threads(atoi(argv[1])) reduction(+:sum)
        for(int j=0; j<4; ++j)  // version 2: for(int j=0; j<100000; ++j)
        {
            double x = pow(j, 3.0);
            x = sqrt(x);
            x = sin(x);
            x = cos(x);
            x = tan(x);
            sum += x;
            double y = pow(j, 3.0);
            y = sqrt(y);
            y = sin(y);
            y = cos(y);
            y = tan(y);
            sum += y;
            double z = pow(j, 3.0);
            z = sqrt(z);
            z = sin(z);
            z = cos(z);
            z = tan(z);
            sum += z;
        }
        if (sum > 100000000)
        {
            break;
        }
    }
    return 0;
}

大多数 OpenMP 实现在程序启动时创建许多线程,并在程序运行期间保留它们。 也就是说,大多数实现不会在执行期间动态创建和销毁线程;这样做会影响性能,并产生严重的线程管理成本。 这种线程管理方法与 OpenMP 的常用用例一致并适用。

当您

增加 OpenMP 线程数时,您看到的减速更有可能是由于在迭代次数很少的循环上施加并行开销。 赫里斯托的回答涵盖了这一点。

您可以将并行区域移到while (true)循环之外,并使用 single 指令使代码的串行部分仅在一个线程中执行。这将消除分叉/联接模型的开销。此外,OpenMP 在迭代次数非常少的大腿循环(如版本 1)上也不是很有用。您基本上是在测量 OpenMP 开销,因为循环内的工作非常快 - 即使是具有超越函数的 100000 次迭代在当前一代 CPU 上也花费不到秒的时间(在 2 GHz 和每个 FP 指令大约 100 个周期时,除了加法,还需要 ~100 毫秒)。

这就是 OpenMP 提供 if(condition) 子句的原因,该子句可用于有选择地关闭小循环的并行化:

#omp parallel for ... if(loopcnt > 10000)
for (i = 0; i < loopcnt; i++)
   ...

还建议将schedule(static)用于常规循环(即用于每次迭代需要大约相同计算时间的循环)。

最新更新