c++ - 在 C++ STL 类型的静态实例上使用 OpenMP threadprivate 指令

标签 c++ stl openmp

考虑以下片段:

#include <map>

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

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

使用 OpenMP 编译失败并显示以下错误消息:

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

我不明白这个。我可以在没有 #pragma 指令的情况下进行编译,这应该意味着 std::map 不是不完整。如果 theMap 是原始类型(double、int...),我也可以编译。

如何创建全局静态 std::map threadprivate

最佳答案

这是一个编译器限制。英特尔 C/C++ 编译器支持 threadprivate 上的 C++ 类,而 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];

请注意,我有填充的原因是为了避免 false sharing .我假设现代 Intel x86 处理器的 64 字节高速缓存行。 __declspec(align(64)) 是一个 MSVC 扩展,该结构位于 64 的边界上。因此,tls 中的任何元素都将位于不同的缓存行上,导致没有虚假共享。 GCC 具有 __attribute__ ((aligned(64)))

为了访问这个简单的 TLS,您可以这样做:

tls[omp_get_thread_num()].theMap;

当然,您应该在 OpenMP 并行结构之一中调用它。好消息是 OpenMP 在 [0, N) 中提供了一个抽象的线程 ID,其中 N 是最大线程数。这可以实现快速简单的 TLS 实现。通常,来自操作系统的 native TID 是任意整数。因此,您最需要的是一个哈希表,其访问时间比简单数组长。

关于c++ - 在 C++ STL 类型的静态实例上使用 OpenMP threadprivate 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8051108/

相关文章:

c++ - 对于这个英语单词列表,什么是好的散列函数?

c++ - setw 没有按预期工作

c++ - OpenCV 的 cvAcc() 有什么作用?

c++ - 为什么偏爱数据结构对齐?

c++ - 如何从字符串中存储和检索 char*?

c++ - unique_ptr 矩阵

c++ - 如果我将它绑定(bind)到 "this", std::bind 是否保留对象的引用/拷贝?

c++ - 是否可以使用 g++ 或 clang++ 获取矢量化报告 - openmp

c++ - map 和 openMP 并行调度

c - 对多线程应用程序使用 perf stat