This is a compiler limitation. The Intel C / C ++ compiler supports C ++ classes on threadprivate , while gcc and MSVC currently cannot.
For example, in MSVC (VS 2010) you get this error (I deleted the class):
static std::map<int,int> theMap; #pragma omp threadprivate(theMap) error C3057: 'theMap' : dynamic initialization of 'threadprivate' symbols is not currently supported
So the workaround is pretty obvious, but dirty. You need to create a very simple local storage. Simple approach:
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];
Please note that the reason I have the supplement is to avoid a false exchange . I assume a 64-byte cache line for modern Intel x86 processors. __declspec(align(64)) is an extension of MSVC that the structure is on border 64. Thus, any elements in tls will be located in another line of the cache, which will lead to a false exchange. GCC has __attribute__ ((aligned(64))) .
To access this simple TLS, you can do this:
tls[omp_get_thread_num()].theMap;
Of course, you must call this inside one of the parallel OpenMP constructs. It's nice that OpenMP provides an abstract thread identifier in [0, N), where N is the maximum number of threads. This provides a quick and fast implementation of TLS. In general, the native TID from the operating system is an arbitrary integer. Thus, you basically need to have a hash table whose access time is longer than a simple array.
source share