并行化共享对象的任务的最佳方法是什么?

时间:2013-10-25 17:21:37

标签: c++ parallel-processing openmp

我正在编码一个物理模拟,主要由一个数组上数百亿次重复操作的中心循环组成。这些操作独立于其他操作(实际上阵列实际上是沿途更改),因此我正在考虑并行化我的代码,因为我可以在我的实验室中运行4或8核计算机。 这是我第一次做同样的事情,我被建议看看openmp。我已经开始使用它编写一些玩具程序,但我真的不确定它是如何工作的,文档对我来说非常神秘。例如,以下代码:

int a = 0;
#pragma omp parallel
  {
    a++;
  }
   cout << a << endl;
在我的计算机上启动

(4核CPU)有时给我4次,其他时间为3或2.这是因为它不等待所有核心执行指令吗?因为我确实需要知道在我的案例中完成了多少次迭代。考虑到我最终想要的东西,我应该寻找除了openmp以外的其他东西吗?

2 个答案:

答案 0 :(得分:0)

当同时写入共享变量(代码中为a)时,您会遇到数据竞争。要避免不同的线程“同时”写入,您必须使用原子赋值或使用互斥锁保护赋值(=互斥)。在OpenMP中,后者通过关键区域

完成
int a = 0;
#pragma omp parallel
{
#pragma omp critical
  {
    a++;
  }
}
cout << a << endl;

(当然,这个特殊的程序没有并行执行任何操作,因此比执行相同操作的序列程序要慢。)

有关详细信息,请阅读openMP文档!但是,我建议你不使用OpenMP,如果你使用的是C ++,则建议使用TBB。它更加灵活。

答案 1 :(得分:0)

您所看到的是race condition的典型示例。四个线程试图增加变量a,他们正在为它而战。有些'输了'而且他们无法增加,所以你看到的结果低于4.

a++命令实际上是一组三个指令:从内存中读取a并将其放入寄存器中,递增寄存器中的值,然后将值重新放入记忆。如果线程1在线程2读取之后但在线程2将新值写回a之前读取a的值,则将覆盖thread2的增量操作。使用#omp critical是一种确保所有读取/递增/写入操作不会被另一个线程中断的方法。

如果需要并行化迭代,可以使用omp parallel for来增加数组中的所有元素。

典型用途:

#pragma omp parallel for
    for (i = 0; i < N; i++)
        a[i]++;