首页 > 解决方案 > OpenMP 线程与静态变量的关联

问题描述

我有一个 C++ 类 C,其中包含一些代码,包括一个只能读取的静态变量,也许还有一个 constexpr 静态函数。例如:

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;

}

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

标签: c++openmp

解决方案


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

非常量静态会很麻烦。大概这些静态有助于执行某种线程同步。如果它们包含经常读取和很少写入的标志,那么为了获得最佳性能,写入器可能会更好地写入多个注册副本(每个区域一个),并且每个线程使用指向适当区域副本的线程本地指针,超过一半(或 3/4)的读者总是很慢。当然,这不再是简单的原子写入,单个互斥体只会让您回到开始的位置。我怀疑这是你自己的代码领域。

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


推荐阅读