c++ - OpenMP/__gnu_parallel 用于 unordered_map

标签 c++ openmp unordered-map gnu-parallel

在我的代码中的某个时刻,我必须对 unordered_map 中的所有元素进行操作。为了加速这个过程,我想使用 openMP,但是天真的方法不起作用:

std::unordered_map<size_t, double> hastTable;

#pragma omp for
for(auto it = hastTable.begin();
    it != hastTable.end();
    it ++){
//do something
}

原因是,unordered_map 的迭代器不是随机访问迭代器。 作为替代方案,我尝试了对 for_each 起作用的 __gnu_parallel 指令。但是下面的代码

#include <parallel/algorithm>
#include <omp.h>

__gnu_parallel::for_each (hashTable.begin(), hashTable.end(),[](std::pair<const size_t, double> & item)
                        {
                          //do something with item.secon
                        });

使用 (gcc 4.8.2) 编译

 g++ -fopenmp -march=native -std=c++11

不并行运行。使用 vector 切换 unordered_map 并使用相同的 __gnu_parallel 指令并行运行。

为什么在无序映射的情况下它不并行运行?有解决方法吗?

下面我给你一些简单的代码,它重现了我的问题。

#include <unordered_map>
#include <parallel/algorithm>
#include <omp.h>

int main(){

//unordered_map                                                                                                                                      
std::unordered_map<size_t, double> hashTable;
double val = 1.;
for(size_t i = 0; i<100000000; i++){
  hashTable.emplace(i, val);
  val += 1.;
}
__gnu_parallel::for_each (hashTable.begin(), hashTable.end(),[](std::pair<const size_t, double> & item)
                        {
                          item.second *= 2.;
                        });

//vector                                                                                                                                             
std::vector<double> simpleVector;
val = 1.;
for(size_t i = 0; i<100000000; i++){
  simpleVector.push_back(val);
  val += 1.;
}
__gnu_parallel::for_each (simpleVector.begin(), simpleVector.end(),[](double & item)
                        {
                          item *= 2.;
                        });

}

期待您的回答。

最佳答案

不支持随机迭代器的容器的规范方法是使用显式 OpenMP 任务:

std::unordered_map<size_t, double> hastTable;

#pragma omp parallel
{
   #pragma omp single
   {
      for(auto it = hastTable.begin(); it != hastTable.end(); it++) {
         #pragma omp task
         {
            //do something
         }
      }
   }
}

这会为每次迭代创建一个单独的任务,这会带来一些开销,因此只有当 //do something 实际上意味着 //do quite a bit of work 时才有意义。

关于c++ - OpenMP/__gnu_parallel 用于 unordered_map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26034642/

相关文章:

C++如何用模板特化或其他方式实现?

c++ - 通过迭代自适应阈值和形状分析检测圆形对象的集群

c++ - unordered_multimap::equal_range 慢

c++ - 无序映射 emplace 返回的对的类型

c++ - std::unordered_multimap 的 bucket 是否只包含具有等效键的元素

c++ - 枚举变量作为动态模板参数

c++ - 尝试将 boost::stacktrace 添加到 CMake 项目时生成错误

c++ - iMac 上的 OpenMP 'slower'? (C++)

c++ - 是否应该尽可能使用前向声明而不是包含?

c - omp ordered 和 omp critical 之间的区别