我需要 std::atomic<bool> 还是 POD bool 足够好?
Do I need std::atomic<bool> or is POD bool good enough?
考虑这段代码:
// global
std::atomic<bool> run = true;
// thread 1
while (run) { /* do stuff */ }
// thread 2
/* do stuff until it's time to shut down */
run = false;
这里需要与原子变量相关的开销吗?我的直觉是布尔变量的 read/write 或多或少是原子的(这是一个常见的 g++/Linux/Intel 设置)并且如果有一些 write/read 时间怪异,我的 运行 线程 1 上的循环因此提前或延迟停止了一次通过,我对此应用程序并不非常担心。
或者我在这里遗漏了一些其他考虑因素?查看 perf,我的代码似乎在 std::atomic_bool::operator bool
中花费了相当多的时间,我宁愿将它放在循环中。
您需要使用 std::atomic
来避免不需要的优化(编译器只读取一次值并且总是循环或从不循环)并在没有强序内存模型的系统上获得正确的行为(x86 是强序的,所以一旦写入完成,下一次读取就会看到它;在其他系统上,如果线程由于其他原因没有刷新 CPU 缓存到主 RAM,则写入可能很长时间都看不到,如果曾经)。
不过您可以提高性能。默认使用 std::atomic
使用 a sequential consistency model 这对于单个标志值来说是过大的。您可以通过使用 load
/store
和显式(且不太严格)的内存排序来加快速度,因此不需要每个 load
使用最偏执的模式来保持一致性。
例如,您可以这样做:
// global
std::atomic<bool> run = true;
// thread 1
while (run.load(std::memory_order_acquire)) { /* do stuff */ }
// thread 2
/* do stuff until it's time to shut down */
run.store(false, std::memory_order_release);
在 x86 机器上,任何低于(默认,最严格的)顺序一致性排序的排序通常最终只会确保指令以特定顺序执行;由于强序内存模型,不需要总线锁定等。因此,除了保证值实际上是从内存中读取的,而不是缓存到寄存器中并重复使用之外,在 x86 上以这种方式使用原子是免费的,在非 x86 机器上,它使您的代码正确(否则它不会).
考虑这段代码:
// global
std::atomic<bool> run = true;
// thread 1
while (run) { /* do stuff */ }
// thread 2
/* do stuff until it's time to shut down */
run = false;
这里需要与原子变量相关的开销吗?我的直觉是布尔变量的 read/write 或多或少是原子的(这是一个常见的 g++/Linux/Intel 设置)并且如果有一些 write/read 时间怪异,我的 运行 线程 1 上的循环因此提前或延迟停止了一次通过,我对此应用程序并不非常担心。
或者我在这里遗漏了一些其他考虑因素?查看 perf,我的代码似乎在 std::atomic_bool::operator bool
中花费了相当多的时间,我宁愿将它放在循环中。
您需要使用 std::atomic
来避免不需要的优化(编译器只读取一次值并且总是循环或从不循环)并在没有强序内存模型的系统上获得正确的行为(x86 是强序的,所以一旦写入完成,下一次读取就会看到它;在其他系统上,如果线程由于其他原因没有刷新 CPU 缓存到主 RAM,则写入可能很长时间都看不到,如果曾经)。
不过您可以提高性能。默认使用 std::atomic
使用 a sequential consistency model 这对于单个标志值来说是过大的。您可以通过使用 load
/store
和显式(且不太严格)的内存排序来加快速度,因此不需要每个 load
使用最偏执的模式来保持一致性。
例如,您可以这样做:
// global
std::atomic<bool> run = true;
// thread 1
while (run.load(std::memory_order_acquire)) { /* do stuff */ }
// thread 2
/* do stuff until it's time to shut down */
run.store(false, std::memory_order_release);
在 x86 机器上,任何低于(默认,最严格的)顺序一致性排序的排序通常最终只会确保指令以特定顺序执行;由于强序内存模型,不需要总线锁定等。因此,除了保证值实际上是从内存中读取的,而不是缓存到寄存器中并重复使用之外,在 x86 上以这种方式使用原子是免费的,在非 x86 机器上,它使您的代码正确(否则它不会).