2

我正在使用 OpenMP 编写 c++ 代码。我有一个全局巨大数组(100,000+ 个元素),将通过在 for 循环中添加值来修改它。有没有一种方法可以有效地让 OpenMP 为并行创建的每个线程维护其本地数组副本,然后在循环后加入?由于线程数是一个变量,我无法事先创建数组的本地副本。如果使用全局副本并通过同步锁解决竞争条件,则性能很糟糕。

谢谢!

编辑:抱歉不清楚。这是一些伪代码,希望可以澄清这种情况:

int* huge_array=new int[N];
memset(huge_array, 0, N*sizeof(int));
#pragma omp parallel for
for (i=0; i<n; i++)
{
  get a value v independently
  get a position p independently
  // I have to set a lock here
  omp_set_lock(&lock);
  huge_array[p] += v;
  omp_unset_lock(&lock);
}

有没有办法提高上面代码的性能?

4

4 回答 4

6

好吧,我终于明白你想做什么了。是的,您的操作方式与使用 ptreads 相同。

std::vector<int> A(N,0);
std::vector<int*> local(omp_max_num_threads());
#pragma omp parallel
{
  int np = omp_get_num_threads();
  std::vector<int> localA(N);
  local[omp_get_thread_num()] = localA.data();

  // add values to local array
  #pragma omp for
  for(int i=0; i<num_values; ++i)
    localA[position()] += value();          // (1)
  // implicit barrier ensures all local copies are ready for aggregation

  // aggregate local copies into global array
  #pragma omp for
  for(int k=0; k<N; ++k)
    for(int p=0; p<np; ++p)
       A[k] += local[p][k];                 // (2)
  // implicit barrier ensures no local copy is deleted before aggregation is done
}

但重要的是同时进行聚合。

于 2013-09-12T20:39:01.183 回答
1

沃尔特的回答中,我相信而不是

std::vector<int*> local(omp_max_num_threads());

它应该是

std::vector<int*> local(omp_get_max_threads());

omp_max_num_threads()不是 OpenMP 中的例行程序。

于 2016-12-23T18:36:38.387 回答
0

使用指令怎么样

'#'pragma omp parallel for private(VARIABLE)

为您的程序(仅带有十字架,而不带有这些'')?

编辑:对于您的代码,我将使用我的指令,在锁定和解锁变量时您不会浪费太多时间......

编辑2:对不起,你不能使用我的代码来解决你的问题,只有当你首先创建一个临时数组来临时存储你的数据时......

于 2013-09-12T20:32:34.743 回答
0

据我所知,您实际上是在填充直方图,直方图position的 bin 是要填充的,并且value是您将添加到该 bin 的权重/值。并行填充直方图相当于进行数组缩减。OpenMP 的 C++ 实现对此没有直接支持,但是,据我了解Fortran 实现的某些版本可以。要使用 OpenMP 在 C++ 中减少数组,我有两个建议。

1.)如果直方图(数组)的 bin 数量远少于将填充直方图的值的数量(这通常是首选情况,因为人们希望每个 bin 中有合理的统计数据),那么您可以填写私人版本并行的直方图,并将它们串行合并到一个关键部分。由于箱的数量远少于值的数量,这应该是有效的。

2.)但是,如果箱的数量很大(正如您的示例似乎暗示的那样),那么也可以并行合并私有直方图,但这有点棘手。此外,需要注意缓存对齐和错误共享。

我展示了如何执行这两种方法,并在以下问题中讨论了一些缓存问题: Fill histograms (array reduction) in parallel with openmp without using a critical section

于 2013-09-25T11:46:38.380 回答