user3658306
user3658306

Reputation: 217

OpenMP increment a count and assign the value to an array

I am new to the OpenMP, not sure what was wrong with this code, the results are not making sense.

Thanks.

#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]);
}

Edit: the cnt outside the parallel region should be 11, most time it was correct, but sometime it gave me 10. For array A I understand why the values do not match with the indices, but I would hope the array A be like this following, is it possible ?

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

Upvotes: 1

Views: 1199

Answers (1)

Z boson
Z boson

Reputation: 33709

Your code has multiple bugs. Let's address the silly one first. You write to N+1 elements but only allocate N elements. Change N to 21 and then change

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

to

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

But your code has another more subtle bug. You're using an induction variable. I don't know an easy way to use induction variables with OpenMP.

In your case one easy fix is not use an induction variable and instead do

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

You can also use a reduction for the final value of cnt but it's redundant and less efficient.

#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;
}

If you really want to use an induction variable then you have to do something like this:

#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;

You can also use a reduction for the final value of cnt but as is clear in the code below it's redundant.

#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;
    }
}

Upvotes: 1

Related Questions