OpenMP - 只创建一次线程

时间:2012-05-14 19:25:28

标签: c++ openmp

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

我准备两个版本的for循环,并在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;
}

2 个答案:

答案 0 :(得分:9)

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

当你增加OpenMP线程的数量时,你看到的减速很可能是在一个迭代次数很少的循环上施加并行开销。 Hristo的答案涵盖了这一点。

答案 1 :(得分:5)

您可以将并行区域移动到while (true)循环之外,并使用single指令使代码的串行部分仅在一个线程中执行。这将消除fork / join模型的开销。 OpenMP在迭代次数很少的thight循环中也不是很有用(比如你的版本1)。您基本上测量OpenMP开销,因为循环内部的工作非常快 - 甚至100000次迭代与超越函数在当前一代CPU上花费不到第二次(在2 GHz和每个FP指令大约100个循环,除了添加,它将会需要~100 ms)。

这就是为什么OpenMP提供了if(condition)子句,可以用来有选择地关闭小循环的并行化:

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

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