我想在 OpenMP 的帮助下并行化这段代码,比如
#pragma omp parallel for
在不同的线程之间划分工作。
什么是有效的方法?这里级别在各种线程之间共享。
这里 make 是一个集合。
for(iter=make.at(level).begin();iter!=make.at(level).end();iter++)
{
Function(*iter);
}
我想在 OpenMP 的帮助下并行化这段代码,比如
#pragma omp parallel for
在不同的线程之间划分工作。
什么是有效的方法?这里级别在各种线程之间共享。
这里 make 是一个集合。
for(iter=make.at(level).begin();iter!=make.at(level).end();iter++)
{
Function(*iter);
}
如果返回的类型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);
}
如果该类型不提供随机访问迭代器,但您的编译器仍支持 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);
}
}
}
这里单个线程执行 for 循环并创建许多 OpenMP 任务。每个任务将Function()
使用 的相应值进行一次调用*iter
。然后每个空闲线程将开始从未完成任务列表中挑选。在并行区域的末尾有一个隐式屏障,因此主线程将尽职尽责地等待所有任务完成,然后再继续执行通过并行区域。
如果您不幸使用 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;
这不是最优雅的解决方案,但它应该可以工作。
编辑:如果我从您的问题标题中理解正确,那么您正在使用集合。这排除了第一个算法,因为集合不支持随机访问迭代器。根据您的编译器对 OpenMP 任务的支持,使用第二种或第三种算法。
似乎并行的变量必须是有符号的int。但我不确定。这是一个关于这个的话题。为什么必须对循环变量进行并行签名?
要在 OpenMP 中使用这种迭代器模式,可能需要重新考虑如何执行循环 -#pragma omp for
因为循环不是简单的整数循环,所以不能使用。我想知道以下是否可行:
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 */
请注意,我必须将您iter++
的next()
调用更改为关键部分中的调用才能使其正常工作。这样做的原因是共享make.at(level)
对象需要记住哪些项目已经被处理。