Рассмотрим следующую последовательную функцию. Когда я распараллеливаю свой код, каждый поток будет вызывать эту функцию из параллельной области (не показано). Я пытаюсь сделать это потокобезопасным и эффективным (быстрым).
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», значение должно быть вычислено и сохранено.
Так куда же мне положить #pragma omp critical
?
Хотя это легко, очень неэффективно ставить #pragma omp critical
вокруг всего этого, поскольку каждый поток будет делать это постоянно, и это часто будет только для чтения.
Есть ли способ реализовать «одностороннюю» critical
или «одностороннюю» lock
процедуру? То есть вышеупомянутые операции с использованием итератора должны быть «заблокированы» только при записи в my_map
в операторе else
. Но несколько потоков должны иметь возможность выполнять вызов .find
одновременно.
Надеюсь, я понимаю. Спасибо.