Это ограничение компилятора.Компилятор Intel C / C ++ поддерживает классы C ++ на threadprivate
, в то время как gcc и MSVC в настоящее время не могут.
Например, в MSVC (VS 2010) вы получите эту ошибку (я удалил класс):
static std::map<int,int> theMap;
#pragma omp threadprivate(theMap)
error C3057: 'theMap' : dynamic initialization of 'threadprivate' symbols is not currently supported
Итак, обходной путь довольно очевидный, но грязный.Вам нужно сделать очень простое локальное хранилище потоков.Простой подход может быть следующим:
const static int MAX_THREAD = 64;
struct MY_TLS_ITEM
{
std::map<int,int> theMap;
char padding[64 - sizeof(theMap)];
};
__declspec(align(64)) MY_TLS_ITEM tls[MAX_THREAD];
Обратите внимание, что причина, по которой у меня есть заполнение, заключается в том, чтобы избежать ложного совместного использования .Я предполагаю, что 64-байтовая строка кэша для современных процессоров Intel x86.__declspec(align(64))
является расширением MSVC, структура которого находится на границе 64. Таким образом, любые элементы в tls
будут расположены на другой строке кэша, что не приведет к ложному совместному использованию.GCC имеет __attribute__ ((aligned(64)))
.
Чтобы получить доступ к этому простому TLS, вы можете сделать это:
tls[omp_get_thread_num()].theMap;
Конечно, вы должны вызвать это внутри одного изOpenMP параллельные конструкции.Приятно то, что OpenMP предоставляет абстрагированный идентификатор потока в [0, N), где N - максимальный номер потока.Это обеспечивает быструю и простую реализацию TLS.Как правило, собственный TID операционной системы - это произвольное целое число.Таким образом, вам в основном нужна хеш-таблица, время доступа которой больше, чем у простого массива.