Очень простым решением вашей проблемы было бы защитить как части чтения, так и обновления вашего кода с помощью директивы critical
OpenMP . Конечно, чтобы уменьшить риск нежелательного взаимодействия / коллизии с каким-либо другим critical
, который у вас уже может быть где-то еще в вашем коде, вы должны дать ему имя, чтобы четко идентифицировать его. И если ваша реализация OpenMP позволяет это (ie версия стандарта достаточно высока), а также, если у вас есть соответствующие знания, вы можете добавить подсказку о том, сколько разногласий вы ожидаете от этого например, обновление между потоками.
Затем я бы посоветовал вам проверить, дает ли эта простая реализация достаточную производительность, а это означает, что влияние директивы critical
не слишком сильно с точки зрения производительности. Если вы довольны исполнением, оставьте все как есть. Если нет, то вернитесь с более точным вопросом, и мы посмотрим, что можно сделать.
Для простого решения код может выглядеть следующим образом (здесь есть подсказка, предполагающая, что ожидается высокий уровень конкуренции, это только пример для вас, а не мое истинное ожидание):
int memoize( int i ) {
static std::map<int,int> memoizer;
bool found = false;
int value;
#pragma omp critical( memoize ) hint( omp_sync_hint_contended )
{
const auto it = memoizer.find( i );
if ( it != memoizer.end() ) {
value = it->second;
found = true;
}
}
if ( !found ) {
// here, we didn't find i in memoizer, so we compute it
value = compute_actual_value_for_memoizer( i );
#pragma omp critical( memoize ) hint( omp_sync_hint_contended )
memoizer[i] = value;
}
return value;
}