在OpenMP中连接数组结果

时间:2013-09-12 20:28:00

标签: c++ arrays multithreading openmp

我正在使用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 个答案:

答案 0 :(得分: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
}

但同时进行聚合也很重要。

答案 1 :(得分:1)

Walter's answer,我相信而不是

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

应该是

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

omp_max_num_threads()不是OpenMP中的例程。

答案 2 :(得分:0)

使用指令

怎么样?

'#'pragma omp parallel for private(VARIABLE)

你的程序(只有十字架,而不是这些'')?

编辑: 对于你的代码,我会使用我的指令,锁定和解锁你的变量时你不会花太多时间......

编辑2: 抱歉,如果您在临时存储数据的位置创建临时数组,则无法使用我的代码解决您的问题...

答案 3 :(得分:0)

据我所知,基本上是填充直方图,其中position是要填充的直方图的bin,而value是要添加到该bin的权重/值。并行填充直方图相当于进行数组缩减。但是,就我所理解的some version of the Fortran implementation而言,OpenMP的C ++实现没有直接的支持。要使用OpenMP在C ++中进行数组缩减,我有两个建议。

1。)如果直方图(数组)的区间数量远小于填充直方图的值的数量(这通常是首选情况,因为每个区域中需要合理的统计数据),那么你可以并行填充直方图的私有版本,并将它们合并到一个关键部分中。由于箱的数量远小于值的数量,因此这应该是有效的。

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

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