2012-05-14 65 views
5

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

我准备了for循环的两个版本,并在1,2和4内核上运行应用程序。
版本1(for循环中的4次迭代):22sec,23sec,26sec。
版本2(for循环中的100000次迭代):20sec,10sec,6sec。你可以看到,当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; 
} 

回答

5

您可以在while (true)环之外将并行区域,并使用single指令使代码的串行部分在只有一个线程执行。这将消除fork/join模型的开销。另外OpenMP对于迭代次数很少的thight循环(如你的版本1)并不是很有用。你基本上是在测量OpenMP的开销,因为循环内部的工作非常快 - 甚至在超过100000次的迭代中,使用超越函数的时间比现在的CPU少2倍(2 GHz,除FP之外大约100个周期,它会采取约100毫秒)。

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

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

它也建议使用schedule(static)定期循环(即for循环中,每迭代需要大约相同的时间来计算)。

8

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

当你增加OpenMP线程的数量时,你看到的减速的可能性很可能低于在具有极少数迭代的循环上施加并行开销。 Hristo的回答涵盖了这一点。