OpenMP递增计数并将值分配给数组

时间:2015-01-30 23:43:19

标签: c openmp

我是OpenMP的新手,不知道这段代码有什么问题,结果没有意义。

感谢。

#include <omp.h>
#include <stdio.h>

#define N 20

int cnt = 0;
int A[N];

int main (int argc, char *argv[]) {
  #pragma omp parallel for
  for (int i = 0; i <= N; i++) {
    if ((i%2)==0) cnt++;
    A[i] = cnt;
    printf("i=%d, cnt=%d\n", i, cnt);
  }
  printf("outside the parallel cnt=%d\n", cnt);

  for (int i = 0; i <= N; i++)
    printf("A[%d]=%d\n", i, A[i]);
}

编辑: 并行区域外的cnt应该是11,大多数时候它是正确的,但有时它给了我10.对于数组AI理解为什么值与索引不匹配,但我希望数组A如下所示,是有可能吗?

A[0]=1 A[1]=1 A[2]=2 A[3]=2 A[4]=3 A[5]=3 A[6]=4 A[7]=4 A[8]=5 A[9]=5 A[10]=6
A[11]=6 A[12]=7 A[13]=7 A[14]=8 A[15]=8 A[16]=9 A[17]=9 A[18]=10 A[19]=10 
A[20]=11

1 个答案:

答案 0 :(得分:1)

您的代码有多个错误。让我们首先解决愚蠢的问题。您写入N+1元素但仅分配N个元素。将N更改为21,然后更改

for (int i = 0; i <= N; i++)

for (int i = 0; i < N; i++)

但是你的代码还有另一个更微妙的错误。您正在使用induction variable。我不知道在OpenMP中使用归纳变量的简单方法。

在您的情况下,一个简单的解决方法是不使用归纳变量,而是使用

#pragma omp parallel for
for (int i = 0; i < N; i++) {
    int j = i / 2 + 1;
    A[i] = j;
}
cnt = N/2;

您还可以使用缩减作为cnt的最终值,但它是多余的且效率较低。

#pragma omp parallel for reduction(+:cnt)
for (int i = 0; i < N; i++) {
    if ((i % 2) == 0) cnt++;
    int j = i / 2 + 1;
    A[i] = j;
}

如果您真的想使用归纳变量,那么您必须执行以下操作:

#pragma omp parallel
{
    int ithread = omp_get_thread_num();
    int nthreads = omp_get_num_threads();
    int start = ithread*N/nthreads;
    int finish = (ithread + 1)*N/nthreads;

    int j = start / 2;
    if (start % 2) j++;
    for (int i = start; i < finish; i++) {
        if ((i % 2) == 0) j++;
        A[i] = j;
    }
}
cnt = N/2;

您还可以使用缩减功能来确定cnt的最终值,但在下面的代码中可以清楚地看出它是多余的。

#pragma omp parallel reduction(+:cnt)
{
    int ithread = omp_get_thread_num();
    int nthreads = omp_get_num_threads();
    int start = ithread*N/nthreads;
    int finish = (ithread + 1)*N/nthreads;

    int j = start / 2;
    if (start % 2) j++;
    for (int i = start; i <finish; i++) {
        if ((i % 2) == 0) {
            j++; cnt++;
        } 
        A[i] = j;
    }
}