所以在SO和整个互联网上,如何使OpenMP易于使用的#pragma
指令与C ++同样易于使用的STL容器配合使用,会有很多困惑和挫折。
每个人都在谈论STL vector
的变通方法,但是非随机访问/双向容器呢,如map
,list
,set
等。?
我遇到了这个问题并设计了一个非常简单明了的解决方法。我在这里为STL map
呈现它,但它显然是可推广的。
串行版:
for (std::map<A,B>::iterator it = my_map.begin();
it != my_map.end();
++it)
{ /* do work with it */ }
我建议的解决方案是将OpenMP与STL map
一起使用:
//make an array of iterators.
int loop_length = my_map.size();
std::map<A,B>::iterator loop_array[ loop_length ];
std::map<A,B>::iterator allocate_it = my_map.begin();
for (int j=0; j<loop_length; ++j)
loop_array[j] = allocate_it++;
// now you can use OpenMP as usual:
#pragma omp parallel for
for (uint j=0; j<loop_length; ++j)
{ /* do work with loop_array[j] */ }
我远非OpenMP的专家,所以我想知道我提议的解决方案是否有效且良好实践。
请假设程序员负责在for循环中对STL容器进行线程安全处理。
最后,我提出的解决方案是否比以下常用的解决方案(see answer to this SO Question)更有效,因为在我的解决方案中,每个线程都不会迭代整个容器?</ p>
#pragma omp parallel
{
for (std::map<A,B>::iterator it = my_map.begin();
it != my_map.end();
++it)
#pragma single nowait
{ /* do work */ }
}
答案 0 :(得分:5)
OpenMP提供从3.0版本开始的task
构造,这对于STL非常有用:
for (std::map<A,B>::iterator it = my_map.begin();
it != my_map.end();
++it)
{
#pragma omp task
{ /* do work with it */ }
}
当然,迭代之间的数据依赖关系不应该存在。