C++ 将共享对象但在其他方面独立的任务并行化的最佳方法是什么?

C++ 将共享对象但在其他方面独立的任务并行化的最佳方法是什么?,c++,parallel-processing,openmp,C++,Parallel Processing,Openmp,我正在编写一个物理模拟程序,主要由一个中央循环组成,在一个阵列上重复数千亿次操作。这些操作是独立于其他操作的(实际上,阵列会随之变化),因此我正在考虑将我的代码并行化,因为我可以让它在实验室的4或8核计算机上运行。 这是我第一次做类似的事情,有人建议我看看openmp。我已经开始用它来编写一些玩具程序,但我真的不确定它是如何工作的,而且文档对我来说相当神秘。例如,以下代码: int a = 0; #pragma omp parallel { a++; } cout <

我正在编写一个物理模拟程序,主要由一个中央循环组成,在一个阵列上重复数千亿次操作。这些操作是独立于其他操作的(实际上,阵列会随之变化),因此我正在考虑将我的代码并行化,因为我可以让它在实验室的4或8核计算机上运行。 这是我第一次做类似的事情,有人建议我看看openmp。我已经开始用它来编写一些玩具程序,但我真的不确定它是如何工作的,而且文档对我来说相当神秘。例如,以下代码:

int a = 0;
#pragma omp parallel
  {
    a++;
  }
   cout << a << endl;
inta=0;
#pragma-omp并行
{
a++;
}

cout在代码中并发写入共享变量(
a
)时,存在数据竞争。要避免不同线程“同时”写入,必须使用原子分配或使用互斥(=互斥)保护分配。在OpenMP中,后者通过关键区域完成

inta=0;
#pragma-omp并行
{
#pragma-omp-critical
{
a++;
}
}

cout你看到的是一个典型的例子。四个线程正试图增加变量
a
,它们正在为之奋斗。有些“丢失”,它们无法增加,因此您会看到低于4的结果

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

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

典型用途:

#pragma omp parallel for
    for (i = 0; i < N; i++)
        a[i]++;
#pragma omp parallel for
对于(i=0;i
操作与阵列沿途的变化无关。不,如果一个操作的结果影响下一个操作的输入,则它们不是独立的。@DavidRodríguez dribeas可以肯定:我的意思是,它实际上是概率性的,对于4个操作,每个操作到一个核心,其中两个操作使用阵列相同部分的概率是10^(-6)所以可以忽略不计。如果你运气不好,不同的任务互相践踏数据,这没关系吧?我的意思是,如果你不在乎程序的正确性,你可能会让你的程序快速地发出刺耳的声音,因为你已经展示了OpenMP的简化操作可能是有用的。@DavidRodríguez dribeas你所说的stomp是什么意思?在这种情况下会发生什么?不要期望这种方法会导致并行程序比串行版本执行得更快。我未经测试的预期是,它实际上会更慢。@HighPerformanceMark是的,当然。这不是重点。这里的重点是如何处理一个简单的数据竞争。@HighPerformanceMark我的程序就是从问题中添加了一个关键区域。
#pragma omp parallel for
    for (i = 0; i < N; i++)
        a[i]++;