提问者:小点点

在源文件中定义静态原子变量不好?


如果我们在源文件(.cpp)中定义静态全局变量,

 // variable defined in cpp
 static std::atomic<double> fps = -1.0;
 static std::atomic<BOOL>isSysUp = FALSE;//WinAPI boolean
 static std::atomic<bool> isMessaginDone = false;

void foo()
{
   while(isSysUp && isMessaginDone ) // with seq.consistent memory order
   {
      //.... some code //
     sleep(1ms);
   }
}
void bar()
{
  if(isSysUp )
  {
    if(/.. condition ../ ) 
      {
         isMessaginDone = false;  

      }    
 }
}

void termi()
{
   isSysUp = false;
}

这里foo用主线程调用,其他函数用子线程调用。

假设函数foo像游戏循环一样每10毫秒调用一次。使用带有静态内部链接的d::atomic并在memory_order_seq_cst进行加载和存储操作会降低性能?并且不安全?

在上述情况下使用std::store(std::memoryy_order_release)、std::load(std::memoryy_order _acquire)来获得线程安全性能,明智吗?

(因为在函数foo中只读取原子布尔值,而不是像在函数bar和termi中那样写一次)


共1个答案

匿名用户

在编译单元中使用静态原子和在编译单元使用静态全局变量一样糟糕或必要。

性能问题可能来自瓶颈。但这更多地与线程之间共享变量的使用和一致性要求有关,而不是微妙的内存排序问题。

尽管这取决于实现,但简单基本类型(如bool或int)上的原子通常是在支持原子CPU指令的情况下实现的,因此可能根本没有性能问题。

例如,使用您的定义:

   while (!isMessaginDone) 

将被转换为

   movzx eax, BYTE PTR isMessaginDone[rip]  ; already atomic CPU instruction
   test al, al

以及类似的设置

   isMessaginDone=true; 

会成为

   mov BYTE PTR isMessaginDone[rip], 1
   mfence           ;  compiler is taking care of the memory ordering

另一方面,实现可以自由使用基于锁的原子实现(例如使用信号量等),这需要昂贵的操作系统调用。但是在这种情况下,使用内存排序进行欺骗不会改变CPU调用的成本,也不会带来您期望的性能提升。

所以不要迷失在过早优化的尝试中。使用原子,查看ASM,如果需要,执行基准测试。