具有静态变量的OpenMP线程亲和力 我有一个C++类C,包含一些代码,包括一个静态变量,它只用于读取,也可能是一个静态的函数。例如: template<std::size_t T> class C { public: //some functions void func1(); void func2() static constexpr std::size_t sfunc1(){ return T; } private: std::size_t var1; std::array<std::size_t,10000> array1; static int svar1; } 模板 C类{ 公众: //一些功能 void func1(); void func2() 静态constexpr std::size\u t sfunc1(){return t;} 私人: 标准:尺寸变量1; std::阵列1; 静态int-svar1; }

具有静态变量的OpenMP线程亲和力 我有一个C++类C,包含一些代码,包括一个静态变量,它只用于读取,也可能是一个静态的函数。例如: template<std::size_t T> class C { public: //some functions void func1(); void func2() static constexpr std::size_t sfunc1(){ return T; } private: std::size_t var1; std::array<std::size_t,10000> array1; static int svar1; } 模板 C类{ 公众: //一些功能 void func1(); void func2() 静态constexpr std::size\u t sfunc1(){return t;} 私人: 标准:尺寸变量1; std::阵列1; 静态int-svar1; },c++,openmp,C++,Openmp,其思想是使用openMP 4.5的线程关联机制来控制执行此类的各种实例的套接字(NUMA体系结构)(因此也将其放置在靠近套接字的内存位置,以避免使用NUMA节点之间的互连)。我的理解是,由于这段代码包含一个静态变量,它在所有类实例之间有效地共享,因此在创建线程时,我将无法控制静态变量的内存位置。这是正确的吗?但是我假设其他非静态变量将位于靠近所用套接字的内存位置?感谢您必须假设线程堆栈、线程绑定malloc和线程本地存储将分配给线程的“本地”内存,因此任何自动或新变量都应该至少在创建它们的线程上

其思想是使用openMP 4.5的线程关联机制来控制执行此类的各种实例的套接字(NUMA体系结构)(因此也将其放置在靠近套接字的内存位置,以避免使用NUMA节点之间的互连)。我的理解是,由于这段代码包含一个静态变量,它在所有类实例之间有效地共享,因此在创建线程时,我将无法控制静态变量的内存位置。这是正确的吗?但是我假设其他非静态变量将位于靠近所用套接字的内存位置?感谢

您必须假设线程堆栈、线程绑定malloc和线程本地存储将分配给线程的“本地”内存,因此任何自动或新变量都应该至少在创建它们的线程上进行优化,尽管我不知道哪些编译器支持这种分配模型;但正如您所说,静态非常量数据只能存在于一个位置。我猜如果编译器识别常量段或构造的常量段,那么在构造之后,它们可以在每个区域复制,然后映射到相同的逻辑地址?同样,我也不知道编译器是否是自动完成的

非常量静力学将会很麻烦。大概这些静力学有助于执行某种线程同步。如果它们包含经常读取而很少写入的标志,那么为了获得最佳性能,写入程序最好写入多个已注册副本(每个区域一个),并且每个线程使用一个指向相应区域副本的线程本地指针,而读卡器的速度总是慢于一半(或3/4)。当然,这不再是一个简单的原子写入,一个互斥锁只会让你回到你开始的地方。我怀疑这是你自己的密码


不应忘记的简单情况是:如果对象在线程之间传递,那么线程可能正在访问非本地对象。

数据放置是操作系统的功能,而不是编译器的功能。它将位于初始化数据的线程的本地。假设您不修改数据,每个线程都将有一个缓存副本,这将最大限度地减少远程访问的问题。这在某种程度上取决于线程亲缘关系,例如,在某些操作系统(如Windows)中,libgomp没有实现的omp_位置