Я использую OpenMP для распараллеливания нашей библиотеки C ++. Там у нас есть разные места, где мы избегаем пересчета некоторых вещей, сохраняя результаты в переменной (т.е. кешируя результат для повторного использования). Однако такое поведение скрыто от пользователя в методах класса. Например, при первом использовании метода кеш будет заполнен. Все последующие использования будут просто читать из кеша.
Моя проблема теперь в том, что в многопоточной программе несколько потоков могут вызывать такой метод одновременно, что приводит к условиям гонки при создании / доступе к кешу. В настоящее время я решаю эту проблему, помещая содержимое кеша в критическую секцию, но это, конечно, все замедляет.
Пример класса может выглядеть следующим образом
class A {
public:
A() : initialized(false)
{}
int get(int a)
{
#pragma omp critical(CACHING)
if (!initialized)
initialize_cache();
return cache[a];
}
private:
bool initialized;
void initialize_cache()
{
// do some heavy stuff
initialized=true;
}
int *cache;
};
Было бы лучше, если бы критическая секция находилась в функции initialize_cache (), поскольку тогда она блокировала бы все потоки только тогда, когда кеш еще не был инициализирован (т.е. только один раз), но это кажется опасным, поскольку тогда несколько потоков могут пытаться для одновременной инициализации кеша.
Есть предложения по улучшению этого? В идеале решение было бы совместимо со старыми версиями OpenMP (даже v2 для Visual Studio ...)
PS: Возможно, об этом спрашивали раньше, но поиски openmp и кеширования выкидывают много вещей в кеши процессора, а это не то, что я хочу знать ...