为什么OpenMP版本更慢?

时间:2011-06-28 13:11:47

标签: c++ openmp

我正在尝试使用OpenMP。我写了一些代码来检查它的性能。在使用Kubuntu 11.04的4核单Intel CPU上,使用OpenMP编译的以下程序比没有OpenMP编译的程序慢大约20倍。为什么呢?

我用g ++编译了它-g -O2 -funroll-loops -fomit-frame-pointer -march = native -fopenmp

#include <math.h>
#include <iostream>

using namespace std;

int main ()
{
  long double i=0;
  long double k=0.7;

  #pragma omp parallel for reduction(+:i)
  for(int t=1; t<300000000; t++){       
    for(int n=1; n<16; n++){
      i=i+pow(k,n);
    }
  }

  cout << i<<"\t";
  return 0;
}

3 个答案:

答案 0 :(得分:15)

问题是变量k被认为是共享变量,因此必须在线程之间同步。 避免这种情况的可能解决方案是:

#include <math.h>
#include <iostream>

using namespace std;

int main ()
{
  long double i=0;

#pragma omp parallel for reduction(+:i)
  for(int t=1; t<30000000; t++){       
    long double k=0.7;
    for(int n=1; n<16; n++){
      i=i+pow(k,n);
    }
  }

  cout << i<<"\t";
  return 0;
}

在下面的评论中跟随Martin Beckett的提示,不是在循环中声明k,而是在循环外声明k const。

否则,ejd是正确的 - 这里的问题似乎并不是很糟糕的并行化,但代码并行化时的优化不好。请记住,gcc的OpenMP实现非常年轻,远非最佳。

答案 1 :(得分:3)

最快的代码:

for (int i = 0; i < 100000000; i ++) {;}

代码稍慢:

#pragma omp parallel for num_threads(1)
for (int i = 0; i < 100000000; i ++) {;}

代码慢2-3倍:

#pragma omp parallel for
for (int i = 0; i < 100000000; i ++) {;}

无论{和}之间是什么。一个简单的 ;或更复杂的计算,相同的结果。我使用gcc和g ++在Ubuntu 13.10 64位下编译,尝试使用不同的参数-ansi -pedantic-errors -Wall -Wextra -O3,并在Intel四核3.5GHz上运行。

我猜线程管理开销是错误的? OMP每次需要时创建一个线程并在之后将其销毁,这似乎并不聪明。我以为会有四(或八)个线程在需要或睡觉时运行。

答案 2 :(得分:0)

我在GCC上观察到类似的行为。但是我想知道在我的情况下它是否与模板或内联函数有某种关系。您的代码是否也在模板或内联函数中?请查看here

但是对于非常短的for循环,你可能会发现一些与线程切换相关的小开销,如你的情况:

#pragma omp parallel for
for (int i = 0; i < 100000000; i ++) {;}

如果你的循环执行了几毫秒甚至几秒的非常长的时间,你应该在使用OpenMP时观察性能的提升。但只有当你有多个CPU时。您拥有的内核越多,OpenMP的性能就越高。