在源文件中定义静态原子变量不好吗?
Define static atomic variable in source file is bad?
如果我们在源文件(.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 每 10ms 调用一次循环,就像 游戏循环 。
使用 std::atomic 和 static 内部链接并执行它们的 load 和 store 在 memory_order_seq_cst 中的操作会降低性能吗?不安全?
使用 std::store(std::memory_order_release), 是否明智std::load(std::memory_order_acquire) 在上述情况下获得线程安全性能?
(因为在函数 foo 中只读取原子 bool 而不是像在函数 [=21 中那样写一次=]bar 和 termi)
在编译单元中使用静态原子与在编译单元中使用静态全局变量一样糟糕或必要。
性能问题可能是由瓶颈引起的。但这更多地与线程之间共享变量的使用和一致性要求有关,而不是微妙的内存排序问题。
虽然这取决于实现,但简单基本类型(例如 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
另一方面,实现可以自由使用基于锁的原子实现(例如使用信号量等),这需要昂贵的 OS 调用。但在这种情况下,再次使用内存排序进行欺骗不会改变 CPU 调用的成本,也不会带来您期望的性能提升。
所以不要迷失在过早优化的尝试中。使用原子,查看 asm,如果需要,执行基准测试。
如果我们在源文件(.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 每 10ms 调用一次循环,就像 游戏循环 。 使用 std::atomic 和 static 内部链接并执行它们的 load 和 store 在 memory_order_seq_cst 中的操作会降低性能吗?不安全?
使用 std::store(std::memory_order_release), 是否明智std::load(std::memory_order_acquire) 在上述情况下获得线程安全性能?
(因为在函数 foo 中只读取原子 bool 而不是像在函数 [=21 中那样写一次=]bar 和 termi)
在编译单元中使用静态原子与在编译单元中使用静态全局变量一样糟糕或必要。
性能问题可能是由瓶颈引起的。但这更多地与线程之间共享变量的使用和一致性要求有关,而不是微妙的内存排序问题。
虽然这取决于实现,但简单基本类型(例如 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
另一方面,实现可以自由使用基于锁的原子实现(例如使用信号量等),这需要昂贵的 OS 调用。但在这种情况下,再次使用内存排序进行欺骗不会改变 CPU 调用的成本,也不会带来您期望的性能提升。
所以不要迷失在过早优化的尝试中。使用原子,查看 asm,如果需要,执行基准测试。