threadprivate 不支持的解决办法

本文探讨了在使用OpenMP时如何将全局静态std::map设置为线程私有的方法。由于部分编译器如GCC和MSVC不支持此特性,文章提供了一种通过创建线程本地存储的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Consider the following snippet:

#include <map>

class A {
    static std::map<int,int> theMap;
#pragma omp threadprivate(theMap)
};

std::map<int,int> A::theMap;

Compilation with OpenMP fails with the following error message:

$ g++ -fopenmp -c main.cpp 
main.cpp:5:34: error: threadprivate A::theMap has incomplete type

I don't understand this. I can compile without the #pragma directive, which should mean thatstd::map is not incomplete. I can also compile if theMap is a primitive type (double, int...).

How do I make a global static std::map threadprivate?


This is a compiler restriction. Intel C/C++ compiler supports C++ classes on threadprivate while gcc and MSVC currently cannot.

For example, in MSVC (VS 2010), you will get this error (I removed 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 make a very simple thread-local storage. A simple approach would be:

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];

Note that the reason why I have padding is to avoid false sharing. I assume that 64-byte cache line for modern Intel x86 processors. __declspec(align(64)) is a MSVC extension that the structure is on the boundary of 64. So, any elements in tls will be located on a different cache line, resulting in no false sharing. GCC has __attribute__ ((aligned(64))).

In order to access this simple TLS, you can do this:

tls[omp_get_thread_num()].theMap;

Of course, you should call this inside one of OpenMP parallel constructs. The nice thing is that OpenMP provides an abstracted thread ID in [0, N), where N is the maximum thread number. This enables a fast and simple TLS implementation. In general, a native TID from operating system is an arbitrary integer number. So, you mostly need to have a hash table whose access time is longer than a simple array.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值