C ++ OpenMP critical: "one-way" blocking?

Consider the following sequential function. When I parallelize my code, each thread will call this function from a parallel area (not shown). I am trying to make this thread safe 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;
    }    
}

Almost every time this function is called, threads will successfully "find" the stored value for their "A" (regardless of what it is). From time to time, when "new A" is called, the value must be calculated and stored.

So where should I put #pragma omp critical?

Although it is easy, it is very difficult to put a #pragma omp criticalaround it all, as each thread will do it constantly, and it will often be read-only.

"" critical "" lock? "" my_map else. .find .

, . .

+3
3

, std::map, . end(). .

, , . , calculate_value , , else A, .

, :

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;
}

: , .

+2

@ChrisA , , .

, #pragma omp critical a name. . , , , .

#pragma omp critical map_protect
{
    std::map::iterator it_find = my_map.find(A);  //many threads do this often.

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

...

#pragma omp critical map_protect
{
    float result_for_A = calculate_value(A);  //should only be done once, really.
    my_map[A] = result_for_A;
}

#pragma omp atomic #pragma omp flush .

atomic (lvalue , ), .

flush , , , , , , , .

+1

OpenMP is a compiler "tool" for automatic loop parallelization, not a library of thread linking or synchronization; therefore, it does not have complex mutexes, such as read / write mutexes: get a write lock, but not a read lock.

Here is an example.

Anyway, Chris A.'s answer is better than mine, though :)

+1
source

All Articles