c ++ OpenMP critical:“one-way”锁定? [英] c++ OpenMP critical: "one-way" locking?

查看:251
本文介绍了c ++ OpenMP critical:“one-way”锁定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下串行函数。当我并行化我的代码,每个线程将从并行区域(未示出)内调用此函数。

Consider the following serial function. When I parallelize my code, every thread will call this function from within the parallel region (not shown). I am trying to make this threadsafe and efficient (fast).

float get_stored_value__or__calculate_if_does_not_yet_exist( int A )
{    
    static std::map<int, float> my_map;

    std::map::iterator it_find = my_map.find(A);  //many threads do this often.

    bool found_A =   it_find != my_map.end();

    if (found_A)
    {
        return it_find->second;
    } 
    else
    {
      float result_for_A = calculate_value(A);  //should only be done once, really.
      my_map[A] = result_for_A;
      return result_for_A;
    }    
}

几乎每次调用此函数时,线程将成功地找到他们的A(无论是什么)的存储值。每次调用一个new A时,都必须计算并存储一个值。

Almost every single time this function is called, the threads will successfully "find" the stored value for their "A" (whatever it is). Every once in a while, when a "new A" is called, a value will have to be calculated and stored.

所以我应该把 #pragma omp critical

虽然很简单,但是效率非常低。 c> #pragma omp critical 所有这一切,因为每个线程将不断地这样做,它通常是只读的情况。

Though easy, it is very inefficient to put a #pragma omp critical around all of this, since each thread will be doing this constantly and it will often be the read-only case.

是否有任何方式实现单向临界或单向常规?也就是说,当在 else 语句中的 my_map 中写入时,上述涉及迭代器的操作应该是但是多个线程应该能够同时执行 .find 调用。

Is there any way to implement a "one-way" critical, or a "one-way" lock routine? That is, the above operations involving the iterator should only be "locked" when writing to my_map in the else statement. But multiple threads should be able to execute the .find call simultaneously.

我希望我有意义。
谢谢。

I hope I make sense. Thank you.

推荐答案

根据这个链接在堆栈溢出插入 std :: map 无效迭代器。对于 end()迭代器也是如此。 这是一个支持链接

According to this link on Stack Overflow inserting into an std::map doesn't invalidate iterators. The same goes for the end() iterator. Here's a supporting link.

不幸的是,如果您不使用关键部分,插入可能会发生多次。此外,由于您的 calculate_value 例程可能在计算上是昂贵的,您必须锁定,以避免这 else 两次使用相同值 A ,然后插入两次。

Unfortunately, insertion can happen multiple times if you don't use a critical section. Also, since your calculate_value routine might be computationally expensive, you will have to lock to avoid this else clause being operated on twice with the same value of A and then inserted twice.

以下是一个示例函数,多重插入:

Here's a sample function where you can replicate this incorrect multiple insertion:

void testFunc(std::map<int,float> &theMap, int i)
{
    std::map<int,float>::iterator ite = theMap.find(i);

    if(ite == theMap.end())
    {
         theMap[i] = 3.14 * i * i;
     }
}

然后这样调用:

std::map<int,float> myMap;

int i;
#pragma omp parallel for
for(i=1;i<=100000;++i)
{
    testFunc(myMap,i % 100);
}

if(myMap.size() != 100)
{
    std::cout << "Problem!" << std::endl;
}

编辑:编辑以纠正earler版本中的错误。

edited to correct error in earler version.

这篇关于c ++ OpenMP critical:“one-way”锁定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆