OpenMP - 只创建一次线程

mch*_*bok 5 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;
}
Run Code Online (Sandbox Code Playgroud)

Hig*_*ark 9

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

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

  • 我对这个主题不太熟悉,但在他关于 OpenMP 的在线课程中,Tim Mattson 多次明确表示,线程是在“#pragma omp parallel”处创建的,并在块的末尾加入。所以这似乎与你的答案相矛盾。 (2认同)

Hri*_*iev 5

您可以将并行区域移动到while (true)循环外部并使用该single指令使代码的串行部分仅在一个线程中执行.这将消除fork/join模型的开销.OpenMP在迭代次数很少的thight循环中也不是很有用(比如你的版本1).你基本上是测量OpenMP的开销,因为循环内的工作就完成了真快-即使有10万超越函数取小于第二电流代CPU上(在2 GHz,每个FP大约100次instruciton比另外其他的,它会迭代需要~100毫秒).

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

#omp parallel for ... if(loopcnt > 10000)
for (i = 0; i < loopcnt; i++)
   ...
Run Code Online (Sandbox Code Playgroud)

建议使用schedule(static)常规循环(即循环,其中每次迭代需要大约相同的时间来计算).