简体   繁体   English

使用openMP和SETS

[英]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. 我希望在OpenMP的帮助下将此代码#pragma omp parallel for例如#pragma omp parallel for以便在不同的线程之间划分工作。

What would be an efficient way? 什么是有效的方式? Here level is shared between the varioud threads. 这里的级别在varioud线程之间共享。

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: 如果make.at(level)返回的类型具有随机访问迭代器并具有持续访问时间,并且如果您的编译器支持最新的OpenMP版本(读取:它不是 MSVC ++),那么您可以直接使用parallel for worksharing指令:

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: 如果类型不提供radom-access迭代器,但您的编译器仍然支持OpenMP 3.0或更高版本,那么您可以使用OpenMP任务:

#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. 这里一个线程执行for循环并创建许多OpenMP任务。 Each task will make a single call to Function() using the corresponding value of *iter . 每个任务将使用*iter的相应值对Function()进行一次调用。 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: 如果你不幸使用MS Visual C ++,那么除了创建一个对象指针数组并使用一个简单的整数循环迭代它之外,你没有太多的选择:

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. 根据编译器对OpenMP任务的支持,使用第二种或第三种算法。

It seems that the variable in a parallel for must be signed int. 似乎并行中的变量必须是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. 要在OpenMP中使用这个迭代器模式,可能需要重新思考如何执行循环 - 你不能使用#pragma omp for因为你的循环不是一个简单的整数循环。 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. 请注意,我必须将iter++更改为关键部分中的next()调用才能使其正常工作。 The reason for this is that the shared make.at(level) object needs to remember which items have already been processed. 原因是共享的make.at(level)对象需要记住哪些项已经被处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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