【问题标题】:C++ population of unordered map using multithreading使用多线程的 C++ 无序映射填充
【发布时间】:2017-04-02 02:42:06
【问题描述】:

我想知道是否有一种方法可以加快名为 (path_from_startend) 的无序地图的填充速度。无序映射始终具有唯一键。

#pragma omp parallel for
    for (int i=start_index;i<end_index;++i){    
        for (int j=start_index;j<end_index;++j){
            string key= to_string(unique_locations[i])+to_string(unique_locations[j]); 
            //dont compute path to itself
            if (i==j){
            }
            else {              
                    vector <unsigned>  path = pathbot.FindPath(unique_locations[i],unique_locations[j],turn_penalty);
                    path_from_startend.insert(make_pair(key,path));

            }
        }

    }  

【问题讨论】:

  • 由于path_from_startend在线程之间共享,插入操作必须进入临界区。那么问题来了,pathbot.FindPath 需要很长时间吗?否则它是没有意义的,因为您正在有效地按顺序填充地图(由于关键部分)。
  • FindPath 是一种 A* 算法,它确实需要一点时间(毫秒)。
  • 那我的回答应该可以帮到你。我更新了它,以匹配您的代码。
  • unordered_map 不能在没有同步的情况下被多个线程一次安全地修改;但是无论如何,插入 unordered_map 对象不太可能是您的瓶颈。首先要做的是分析您的进程并查看 CPU 大部分时间花在哪里;例如,您可能会发现大部分时间都花在创建 to_string() 调用中的字符串上,在这种情况下,您可能会考虑以比文本字符串其他(更有效)的格式存储数据。

标签: c++ multithreading hashtable unordered


【解决方案1】:

你可以试试下面的模式是否能让你加快速度。您基本上是在填充部分地图,然后将其合并到整个地图中。加速很大程度上取决于元素的构造和插入需要多长时间。如果您的元素构建和插入成本低廉,那么您的加速甚至可能是负数,因为对于每个部分地图,它必须遍历整个地图来搜索重复项。

#pragma omp parallel
{
  std::unordered_map < std::string, std::vector < unsigned > > partial;

  #pragma omp for
  for (int i = start_index; i < end_index; ++i)
  {    
    for (int j = start_index; j < end_index; ++j)
    {
      std::string key = std::to_string(unique_locations[i])
                      + std::to_string(unique_locations[j]); 

      //dont compute path to itself
      if (i != j)
      {              
        std::vector<unsigned> path = pathbot.FindPath(unique_locations[i],
                                                      unique_locations[j],
                                                      turn_penalty);
        partial.insert(std::make_pair(key,path));
      }
    }
  }

  #pragma omp critical
  path_from_startend.insert(partial.begin(),partial.end());
}

【讨论】:

  • 感谢您的指点,它确实减少了我的时间。但是,正如@Jeremy 提到的那样,我发现:1)使用字符串作为键非常昂贵 2)我可以稍微更改算法以使其成为 O(n) 操作而不是 O(n^2)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多