3

I'm trying to use a task construct for my C++/OpenMP program:

#pragma omp parallel
    {
        typename ClusterNormal<DIM>::VectorMean ResultMeanThread;
        ResultMeanThread.setZero();
        #pragma omp single
        for(list<unsigned int>::const_iterator it=IDLeft.cbegin(); it!=IDLeft.cend(); it++)
        {
            #pragma omp task
            {
                ResultMeanThread += Data[*it];
            }
        }
}

This code is computing the sum of some VectorMean (it doesn't mind what they are, but they have operator + defined) for the elements of data indicated in IDLeft.

Every thread initialize VectorMean with all zeros. My problem is that after the for loop, ResultMeanThread is still composted of all zeros.

When a task is executed, the sum is computed correctly, but after the task execution,ResultMeanThread is always re-initialised to zeros.

How could I fix it? I'm using tasks because of the lists, but my code isn't working.

matsjoyce
  • 5,744
  • 6
  • 31
  • 38
Darko
  • 1,448
  • 4
  • 27
  • 44
  • shouldn't `ResultMeanThread` be declared before parallel region and marked as a shared variable? also, is it safe to apply `+=` operation in parallel to an object of type `VectorMean`? – Piotr Skotnicki Dec 16 '14 at 10:05
  • I've created `ResultMeanThread` to be private for each thread. I think that using += operator with a shared variable isn't a good idea because of race conditions... – Darko Dec 16 '14 at 10:10
  • After this code, there's a sum of `ResultmeanThread` with single construct – Darko Dec 16 '14 at 10:11
  • can you show what happens later? – Piotr Skotnicki Dec 16 '14 at 10:12
  • This program is for statistical computing, the function simlpy computes mean of some vectors. So I have vectors of all zeros like output – Darko Dec 16 '14 at 11:34
  • you said there is a `single` construct afterwards, would you mind showing it? – Piotr Skotnicki Dec 16 '14 at 11:37
  • Answer found. Thanks for help: error was in considering `ResultMeanThread` private, like you posted in your first comment – Darko Dec 17 '14 at 08:58

1 Answers1

1

I've found that the problem was the declaration of ResultMeanThread like private variable. I tried this code, declaring a vector of ResultMeanThread like shared variable (length of vector is nember of threads) so every thread access only one element of the vector (no race conditions).

In the previous code, every ResultMeanThread was zero because of task construct. Every time that a task is executed, private variables are set to their initial value. I have to use task construct because of list

Here's the code:

vector<typename ClusterNormal<DIM>::VectorMean> ResultMeanThread;
typename ClusterNormal<DIM>::VectorMean ResultMeanFinal;

//here i set initial values to zero, and number of vector elements equal to total number of threads

#pragma omp parallel
{
    #pragma omp single
    for(list<unsigned int>::const_iterator it=IDLeft.cbegin(); it!=IDLeft.cend(); it++)
    {
        #pragma omp task
        {
            ResultMeanThread[omp_get_thread_num()] += Data[*it];
        }
    }
    #pragma omp taskwait

    // Final sum
    #pragma omp critical
    {
        ResultMeanFinal+=ResultMeanThread[omp_get_thread_num()];
    }
}
Darko
  • 1,448
  • 4
  • 27
  • 44