C++ 使用openmp在地图上进行迭代

C++ 使用openmp在地图上进行迭代,c++,C++,我尝试用OpenMP迭代C++中的映射,但是我得到了三条错误信息: 我的循环的初始化、终止和增量的形式不正确,而且我对使用openmp非常陌生,所以有没有办法在获得与串行循环相同的结果的同时绕过这个问题?下面是我使用的代码 map< int,string >::iterator datIt; #pragma omp parallel for for(datIt=dat.begin();datIt!=dat.end();datIt++) //construct the distance

我尝试用OpenMP迭代C++中的映射,但是我得到了三条错误信息: 我的循环的初始化、终止和增量的形式不正确,而且我对使用openmp非常陌生,所以有没有办法在获得与串行循环相同的结果的同时绕过这个问题?下面是我使用的代码

map< int,string >::iterator datIt;
#pragma omp parallel for
for(datIt=dat.begin();datIt!=dat.end();datIt++) //construct the distance matrix
{
...............
}
map::迭代器datIt;
#pragma-omp并行
for(dait=dat.begin();dait!=dat.end();dait++)//构造距离矩阵
{
...............
}

您的OpenMP实现可能与STL迭代器不兼容。虽然存在一些问题,但我认为您会发现您的实现不支持这种行为。我遇到的大多数OpenMP实现最多是2.5版,微软C++是2。我知道支持3的唯一编译器是英特尔C++编译器。 还有几点,您应该使用std::begin和std::end。此外,您需要将循环不变量声明为private,或者让OpenMP自行解决,如下所示:

#pragma omp parallel for
for(map< int,string >::iterator datIt = std::begin(dat);
    datIt != std::end(dat);
    datIt++)
{
     //construct the distance matrix...
}
#pragma omp parallel for
对于(map::迭代器dait=std::begin(dat);
datIt!=标准::结束(dat);
datIt++)
{
//构造距离矩阵。。。
}

但是如果没有3.0支持,这就无关紧要了。

如果有帮助的话,试试这种方法

#pragma omp parallel for shared(dat) private(datIt) 
for(map< int,string >::iterator datIt=dat.begin();datIt!=dat.end();datIt++) 
{
 ...............
}
共享(dat)专用(datIt)的pragma omp并行 对于(map::迭代器datIt=dat.begin();datIt!=dat.end();datIt++) { ............... }
OpenMP 3.0现在在gcc上可用,英特尔编译器具有允许线程将任务委托给线程池的任务指令

灵感来源:我写了这样的代码,对我来说很好:

map< int,string >::iterator datIt;
...
#pragma omp parallel for
#pragma omp single nowait
 {
  for(datIt=dat.begin();datIt!=dat.end();datIt++) //construct the distance matrix
  {
   #pragma omp task firstprivate(datIt)
   {
    ...............
   } 
  }
 }
map::迭代器datIt;
...
#pragma-omp并行
#pragma-omp-single-nowait
{
for(dait=dat.begin();dait!=dat.end();dait++)//构造距离矩阵
{
#pragma omp任务第一专用(datIt)
{
...............
} 
}
}
一个任务(单指令)在整个映射上循环,并将映射中每个元素要执行的每个任务放入一个任务池中。其他OMP线程处理任务仍保留在此池中。其他OMP任务无需等待for循环结束以开始任务处理(nowait)。每个任务在映射到进程的元素中都有一个指针(firstprivate(datIt))


约束:每个任务都必须是独立的,并且在结束之前地图不得更改

也可以通过使用一个简单的基于索引的for循环,并使用
std::advance
来到达特定的映射元素。OpenMP 2.0非常支持基于索引的for循环

#pragma omp parallel for
    for(int i = 0; i < dat.size(); i++) {
        auto datIt = dat.begin();
        advance(datIt, i);
        //construct the distance matrix using iterator datIt
    }
#pragma omp parallel for
对于(int i=0;i

在每个线程中,迭代器<代码> DATT< <代码>将指向一个映射项,并可以用于对其执行操作。

GCC支持OpenMP 3,因为版本4.4,并且将支持版本4.7中的3.1,所以它主要是在石器时代中被卡住的Visual C++。此外,即使使用openmp 3.0,也只允许
随机访问迭代器
作为循环变量,但
映射
仅支持
双向迭代器
,因此这没有帮助。为什么
std::begin
std::end
比成员函数更受欢迎,我看不出这有什么好处,因为它只调用成员函数。@Grizzly我不知道GCC OpenMP支持,谢谢。您应该使用非成员begin(…)和end(…),因为它们可以专门用于支持缺少begin和end成员函数的容器。这就强调了泛型编程,这是C++的全部优点。如果你不相信我的话,那就接受吧。考虑到代码中明确提到了迭代器的类型,这并没有使它更通用。此外,
std::begin
通常不能专门用于缺少成员函数的容器,因为不能部分专门化函数模板,并且不允许在
std
中添加重载。为了使它更通用,您需要使用非限定版本(
begin()
end()
)以及使用命名空间std的
使用std::begin;使用std::end
,因为我假设容器更可能具有MemberFunction,那么独立名称空间版本也不是自C++11以来唯一可用的独立版本,所以对于许多程序员来说还不是一个选项?我并不是真的不同意为更通用的接口使用自由函数的原则,但是你的答案没有提供任何额外的通用性,这使得你的建议有点像pointless@Grizzly首先,我并不是仅在示例的上下文中给出这个建议,您应该保持一致并坚持最佳实践。其次,专业化std::begin或std::end不需要部分专业化。第三,您不应该过载标准库函数,但是您可以对它们进行专门化。第四,const char*确实有.begin/end(),这是许多示例中的一个。最后,VS2010支持std::begin/end(),GCC4.6以后的版本也支持:除此之外,它们是一对4行函数,总共对标准库进行了8行的微小更改。