Search code examples
c++taskopenmpparallel.for

OpenMP taskloop inside task


I am using the OpenMP taskloop construct inside a task construct:

double compute(int input) {
  int array[4] = {0};
  double value = input;

  #pragma omp taskloop private(value)
  for(int i=0; i<5000000; i++) {                                                                                                       
    // random computation, the result is not meaningful
    value *= std::tgamma(std::exp(std::cos(std::sin(value)*std::cos(value))));
    int tid = omp_get_thread_num();
    array[tid] ++;
  }

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

  return value;
}

int main (int argc, char *argv[]) {
  omp_set_nested(1);
  omp_set_num_threads(4);  // 4 cores on my machine

  #pragma omp parallel 
  {
    #pragma omp single
    {
      #pragma omp task
      { compute(omp_get_thread_num()); }
    }
  }                                                                                                     
 }

The resulting array is all 0. However, if I change the taskloop to parallel for:

  #pragma omp parallel for private(value)
  for(int i=0; i<5000000; i++) {
    value *= std::tgamma(std::exp(std::cos(std::sin(value)*std::cos(value))));
    int tid = omp_get_thread_num();
    array[tid] ++; 
  }

Then the result of the array is 1250000 for each index. Is there anything wrong in my use of taskloop construct?


Solution

  • Well by @Cimbali's confirmation, it seems that your issue is that the array is not being shared among threads. Since you did not explicitly say that the variable array is shared or private, OpenMP will determine it by its rules. Tasks have a special data sharing attribute compared to parallel for. I couldn't find anything that specifies the rules explicitly. This was the best I could find. Try specifying a default clause and that the array variable is shared.