【问题标题】:Update a hash map inside OpenMP for loop更新 OpenMP for 循环中的哈希映射
【发布时间】:2017-05-01 20:44:36
【问题描述】:

我正在尝试将 openmp 用于 for 循环,我试图在其中插入/更新哈希映射 (std::unordered_map)

哈希映射和键实际上是一个类的成员,所以我分配了指针来表示它们的地址。键也是一个全局函数返回的哈希值。

以下似乎是最简单的方法,但哈希映射未正确更新。有些东西是错的,但我不知道如何解决。在此先感谢。

void MyClass::ProcessBuffer(void)
{
    omp_set_num_threads(4);
    std::unordered_map<unsigned long long,unsigned int>* hashptr=&m_sequencehash;
    std::vector<std::string>* bufferptr=&m_buffer;
    unsigned int sizevec=m_kmer_size;
    size_t i;
    #pragma omp parallel for
    for (i=0; i<READSTR_BUF_SIZE;++i)
    {
        ++(*hashptr)[_hash((*bufferptr)[i],sizevec)];
    }

}

【问题讨论】:

  • std::unordered_map 不是线程安全的,因此您的代码存在竞争条件,从而导致未定义的行为。
  • 只是好奇你将从并行操作中获得的性能提升,最终需要锁定线程安全?!
  • 您可能会考虑使用 TBB 并发 hashmap threadingbuildingblocks.org/docs/help/tbb_userguide/… 您不需要使用 TBB 的其余部分,尽管这也可能有意义!
  • 并发映射对于此目的来说是一种过度杀伤,因为它只需要在初始化步骤期间并发访问。但是,内存中的 map-reduce 库非常适合这种情况。

标签: c++ multithreading openmp


【解决方案1】:

解决这个问题的最简单方法是为每个线程创建一个新映射,然后将它们按顺序减少到一个映射。这是一个经典的 map-reduce 场景。

int s = omp_get_num_threads();
std::unordered_map<unsigned long long,unsigned int> res[s];

// Map step
#pragma omp parallel for
for (i=0; i<READSTR_BUF_SIZE;++i)
{
    int t = omp_get_thread_num();
    res[t][_hash((*bufferptr)[i],sizevec)]++;
}

// Reduce step
for (int i=0; i < s; i++) {
    for (auto r : res[s]) {
        (*hashptr)[r.first] += r.second;
    }
}

同时执行归约可能很危险,因为您仍然必须同时访问同一个映射。如果不知道 map 的实现,就无法确定这是安全的。

或者,您可以通过将不同的哈希间隔放在不同的桶中来在不同的映射之间划分哈希值。这将防止不同线程在 reduce 步骤中访问相同的哈希值。然而,在小数据集上,很难找到具有少量桶的良好分区函数。与串行方法相比,使用太多存储桶可能会产生大量开销。

【讨论】:

  • 答案是在正确的轨道上,但是parallel forres/访问r的定义是错误的。您还应该使用适当的减少而不是手动减少。另请参阅this answer
  • 谢谢,我修复了对 res 的访问权限。
  • 使用适当的归约是危险的,因为您仍然必须同时访问同一个地图。我不知道地图的实现,所以我不能确定这是安全的。
  • 您的代码中仍然只有一张共享地图。虽然我在标准中找不到一些东西,但我可以保证,处理相同数据的归约组合器是相互排他地执行的,并且具有适当的内存隔离。否则我见过的所有隐式和用户声明的组合器都是错误的。
  • 不,您不需要分配新地图 - 输入之一也是组合器的输出。也不要假设log(nthreads) 操作(related answer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 2015-06-05
相关资源
最近更新 更多