OpenMP和优化向量操作

时间:2012-03-30 09:15:26

标签: c++ optimization openmp

我正在运行一个非常沉重但非常平行的算法。

我一直在寻找加速它的方法,我注意到我的最慢操作是我的VecAdd功能(它在6000左右的宽矢量上被调用了数千次)。

实施如下:

bool VecAdd( float* pOut, const float* pIn1, const float* pIn2, unsigned int num )
{
    for( int idx = 0; idx < num; idx++ )
    {
        pOut[idx]   = pIn1[idx] + pIn2[idx];
    }
    return true;
}

它是一个非常简单的循环,但所有添加都可以并行执行。我的第一个优化选项是转移到使用SIMD,因为我可以轻松地将速度提高近4倍。

然而,我也对使用OpenMP并让它自动为for循环进行线程化的可能性感兴趣(可能会给我一个4倍的加速,总共16x的SIMD)。

然而它确实运行缓慢。循环完成后,处理我的示例数据大约需要3.2秒。如果我插入

#pragma omp parallel for
在for循环之前的

我假设它会将几个添加块添加到其他线程中。

不幸的是,结果是处理我的示例数据需要大约7秒钟。

现在我明白我的很多问题都是由设置线程等的开销造成的,但我仍然感到惊讶的是它运行的速度有多慢。

是否有可能通过某种方式提前设置线程池来加快速度,或者我永远无法对抗这些开销?

关于我是否可以使用OpenMP很好地解决这些建议的任何想法都将非常感谢!

1 个答案:

答案 0 :(得分:4)

你的循环应与#pragma omp parallel for并行化。 但是,我认为问题在于您不应该在该级别进行并行化。你说这个函数被调用数千次,但只能运行6000个浮点数。在更高级别进行并行化,以便每个线程负责对VecAdd的thounsands / 4调用。现在你有这个算法:

  1. 列表项
  2. 连续执行
  3. (重新)启动线程
  4. 做简短的计算
  5. 同步线程(在for循环结束时)
  6. 返回序列号
  7. 更改它,使其在最高级别平行。

    内存带宽当然很重要,但它不会导致比串行执行慢。