简体   繁体   中英

Using openMP with SETS

I wanted to parallelize this code with the help of OpenMP with something like #pragma omp parallel for to divide the work amongst the different threads.

What would be an efficient way? Here level is shared between the varioud threads.

Here make is a set.

for(iter=make.at(level).begin();iter!=make.at(level).end();iter++)
{
    Function(*iter);
}

If the type returned by make.at(level) has random-access iterators with constant access time and if your compiler supports recent enough OpenMP version (read: it is not MSVC++) then you can directly use the parallel for worksharing directive:

obj = make.at(level);
#pragma omp parallel for
for (iter = obj.begin(); iter != obj.end(); iter++)
{
    Function(*iter);
}

If the type does not provide radom-access iterators but still your compiler supports OpenMP 3.0 or newer, then you can use OpenMP tasks:

#pragma omp parallel
{
    #pragma omp single
    {
        obj = make.at(level);
        for (iter = obj.begin(); iter != obj.end(); iter++)
        {
            #pragma omp task
            Function(*iter);
        }
    }
}

Here a single thread executes the for loop and creates a number of OpenMP tasks. Each task will make a single call to Function() using the corresponding value of *iter . Then each idle thread will start picking from the list of unfinished tasks. At the end of the parallel region there is an implicit barrier so the master thread will dutifully wait for all tasks to finish before continuing execution past the parallel region.

If you are unfortunate enough to use MS Visual C++, then you don't have much of a choice than to create an array of object pointers and iterate over it using a simple integer loop:

obj = make.at(level);
obj_type* elements = new obj_type*[obj.size()];
for (i = 0, iter = obj.begin(); i < obj.size(); i++)
{
    elements[i] = &(*iter++);
}

#pragma omp parallel for
for (i = 0; i < obj.size(); i++)
{
    Function(*elements[i]);
}

delete [] elements;

It's not the most elegant solution but it should work.

Edit: If I understand correctly from the title of your question, you are working with sets. That rules out the first algorithm since sets do not support random-access iterators. Use either the second or the third algorithm depending on your compiler's supports for OpenMP tasks.

It seems that the variable in a parallel for must be signed int. But I'm not sure. Here is a topic about this. Why must loop variables be signed in a parallel for?

To use this iterator pattern with OpenMP probably requires some rethinking of how to perform the loop - you can't use #pragma omp for since your loop isn't a simple integer loop. I wonder if the following would work:

iter = make.at(level).begin();
end  = make.at(level).end();

#pragma omp parallel private(iter) shared(make,level,end)
{
    #pragma omp single
    func(iter);                      /* only one thread does the first item */

    while (1)
    {
        #pragma omp critical
        iter = make.at(level).next(); /* each thread gets a different item */

        if (iter == end)
            break;

        func(iter);
    }
} /* end parallel block */

Note that I had to change your iter++ into a next() call in a critical section to make it work. The reason for this is that the shared make.at(level) object needs to remember which items have already been processed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM