为什么这个for循环使用OpenMP不会更快?

时间:2015-01-12 13:43:01

标签: c++ performance parallel-processing openmp

我从一个更大的2D程序中提取了这个简单的成员函数,它所做的只是一个for循环访问三个不同的数组并进行数学运算(1D卷积)。我一直在测试使用OpenMP来加快这个特定的功能:

void Image::convolve_lines()
{
  const int *ptr0 = tmp_bufs[0];
  const int *ptr1 = tmp_bufs[1];
  const int *ptr2 = tmp_bufs[2];
  const int width = Width;
#pragma omp parallel for
  for ( int x = 0; x < width; ++x )
    {
    const int sum = 0
      + 1 * ptr0[x]
      + 2 * ptr1[x]
      + 1 * ptr2[x];
    output[x] = sum;
    }
}

如果我在debian / wheezy amd64上使用gcc 4.7,整个程序在8 CPU机器上执行速度要慢很多。如果我在debian / jessie amd64上使用gcc 4.9(这台机器上只有4个CPU),整个程序的执行效果差别很小。

使用time进行比较: 单核运行:

$ ./test black.pgm out.pgm  94.28s user 6.20s system 84% cpu 1:58.56 total

多核运行:

$ ./test black.pgm out.pgm  400.49s user 6.73s system 344% cpu 1:58.31 total

其中:

$ head -3 black.pgm
P5
65536 65536
255

因此Width在执行期间设置为65536

如果重要的话,我正在使用cmake进行编译:

add_executable(test test.cxx)
set_target_properties(test PROPERTIES COMPILE_FLAGS "-fopenmp" LINK_FLAGS "-fopenmp")

CMAKE_BUILD_TYPE设置为:

CMAKE_BUILD_TYPE:STRING=Release

暗示-O3 -DNDEBUG

我的问题是,为什么这个for循环使用多核不会更快?阵列上没有重叠,openmp应该平均分割内存。我不知道瓶颈来自哪里?

编辑:正如评论所述,我将输入文件更改为:

$ head -3 black2.pgm
P5
33554432 128
255

所以Width现在在执行期间设置为33554432(应该考虑足够)。现在时间显示:

单核运行:

$ ./test ./black2.pgm out.pgm  100.55s user 5.77s system 83% cpu 2:06.86 total

多核运行(出于某种原因,cpu%总是低于100%,这表示根本没有线程):

$ ./test ./black2.pgm out.pgm  117.94s user 7.94s system 98% cpu 2:07.63 total

1 个答案:

答案 0 :(得分:2)

我有一些一般性意见:

<强> 1。在优化代码之前,请确保数据是16字节对齐的。这对于想要应用的优化非常重要。如果数据被分成3个部分,最好添加一些虚拟元素,使3个部分的起始地址全部为16字节对齐。通过这样做,CPU可以轻松地将数据加载到缓存行中。

<强> 2。在实现openMP 之前,确保简单函数已向量化。大多数情况下,使用AVX / SSE指令集应该可以为您提供2到8倍的单线程改进。对于您的情况非常简单:创建一个恒定的mm256寄存器并将其设置为值2,并将8个整数加载到3个mm256寄存器。使用Haswell处理器,可以一起完成一次加法和一次乘法。所以理论上,如果AVX管道可以填充,循环应该加速12倍!

第3。有时并行化会降低性能:现代CPU需要数百到数千个时钟周期才能预热,进入高性能状态并扩展频率。如果任务不够大,很可能在CPU预热之前完成任务,并且无法通过并行获得速度提升。并且不要忘记openMP也有开销:线程创建,同步和删除。另一种情况是内存管理不善。数据访问非常分散,所有CPU内核都处于空闲状态并等待来自RAM的数据。

我的建议:

你可能想尝试英特尔MKL,不要重新发明轮子。库优化到极端,没有浪费时钟周期。可以与串行库或并行版本链接,如果可以并行,则可以保证速度提升。