为什么这个OpenMP程序比单线程慢?

时间:2011-07-12 21:34:18

标签: c++ multithreading optimization openmp single-threaded

请查看此代码。

单线程程序:http://pastebin.com/KAx4RmSJ。编译:

  

g ++ -lrt -O2 main.cpp -o nnlv2

使用openMP多线程:http://pastebin.com/fbe4gZSn 编译:

  

g ++ -lrt -fopenmp -O2 main_openmp.cpp -o nnlv2_openmp

我在双核系统上测试过它(所以我们有两个并行运行的线程)。但是多线程版本比单线程版本慢(并显示不稳定的时间,尝试运行几次)。怎么了?我在哪里弄错了?

一些测试:

单螺纹:

Layers Neurons Inputs --- Time (ns)

10 200 200 --- 1898983

10 500 500 --- 11009094

10 1000 1000 --- 48116913

多线程:

Layers Neurons Inputs --- Time (ns)

10 200 200 --- 2518262

10 500 500 --- 13861504

10 1000 1000 --- 53446849

我不明白出了什么问题。

4 个答案:

答案 0 :(得分:2)

您的目标是研究OpenMP,还是让您的计划更快?如果是后者,那么编写乘法 - 加法代码,减少传递次数以及合并SIMD将更有价值。

步骤1:组合循环并使用multiply-add:

// remove the variable 'temp' completely
for(int i=0;i<LAYERS;i++)
{
  for(int j=0;j<NEURONS;j++)
  {
    outputs[j] = 0;

    for(int k=0,l=0;l<INPUTS;l++,k++)
    {
      outputs[j] += inputs[l] * weights[i][k];
    }

    outputs[j] = sigmoid(outputs[j]);
  }

  std::swap(inputs, outputs);
}

答案 1 :(得分:2)

使用-static和-p进行编译,运行然后使用gprof解析gmon.out:

45.65%gomp_barrier_wait_end

这是在opemmp的障碍例程中花了很多时间。这是等待其他线程完成所花费的时间。因为你多次运行并行for循环(LAYERS),所以你失去了并行运行的优势,因为每次并行for循环结束时,都会有一个隐式屏障调用,在所有其他线程完成之前不会返回。

答案 2 :(得分:0)

在其他任何事情之前,在多线程配置上运行测试并确保procexp或任务管理器将显示100%的CPU使用率。如果没有,那么您不使用多个线程也不使用多个处理器核心。

另外,取自维基:

环境变量

一种改变OpenMP应用程序执行功能的方法。用于控制循环迭代调度,默认线程数等。例如,OMP_NUM_THREADS用于指定应用程序的线程数。

答案 3 :(得分:0)

我没看到你实际使用OpenMP的位置 - 在主循环上方尝试#pragma omp parallel ...(例如documented here

缓慢可能来自包括OpenMP和初始化,添加代码膨胀或以其他方式更改编译,因为您引入的编译器标志启用它。或者,循环非常小且简单,以至于线程开销远远超过性能增益。