c ++ 11 atomic是否自动解决变量读写上的多核竞争?
Does c++11 atomic automatically solves multi-core race on variable read-write?
我知道当多个线程读写变量时,atomic 会在类型 "T" 变量上应用锁,确保只有其中一个线程在执行 R/W.
但是在多cpu核计算机中,线程可以运行在不同的核上,不同的核会有不同的L1-cache,L2-cache,同时共享L3-cache。我们知道有时C++编译器会优化一个变量存储在寄存器中,这样如果一个变量没有存储在内存中,那么变量上的不同核心缓存之间就没有内存同步。
所以我的 worry/question 是,如果一个原子变量被编译器优化为某个寄存器变量,那么它就不会存储在内存中,当一个核心写入它的值时,另一个核心可能会读出一个过时的值, 正确的?这个数据的一致性有没有保证?
谢谢。
您可能正在寻找这个:
[intro.progress]/18 An implementation should ensure that the last value (in modification order) assigned by an atomic or synchronization operation will become visible to all other threads in a finite period of time.
Atomic 并不像您模糊描述的那样 "solve"。它为基于顺序的内存一致性提供了某些非常具体的保证。
各种编译器在不同平台上以不同方式实现这些保证。
在 x86/64 上,没有锁用于原子整数和达到合理大小的指针。并且硬件提供了比标准要求更强的保证,使得一些更深奥的选项等同于完全一致。
我无法完全回答您的问题,但我可以为您指明正确的方向;您需要了解的主题是 "the C++ memory model".
也就是说,存在原子是为了避免您描述的确切问题。如果您要求完全的内存顺序一致性,并且线程 A 修改 X,然后修改 Y,则没有其他线程可以看到 Y 被修改但 X 看不到。C++ 标准没有指定如何提供这种保证;缓存行失效,使用特殊指令进行访问,禁止编译器进行某些基于寄存器的优化等都是编译器所做的事情。
请注意,C++ 内存模型已针对 C++17 进行了改进、错误修复和完善,以描述新并行算法的行为并允许它们在具有正确标志的 GPU 硬件(以及其他位置)上高效实施,反过来又影响了新 GPU 硬件提供的保证。所以谈论内存模型的人可能会很兴奋并且谈论比您主要关注的 C++11 问题更多的现代问题。
这是一个复杂的大话题。编写您认为可移植的代码真的很容易,但只能在特定平台上运行,或者通常只能在您测试过的平台上运行。但这只是因为线程很难。
我知道当多个线程读写变量时,atomic 会在类型 "T" 变量上应用锁,确保只有其中一个线程在执行 R/W.
但是在多cpu核计算机中,线程可以运行在不同的核上,不同的核会有不同的L1-cache,L2-cache,同时共享L3-cache。我们知道有时C++编译器会优化一个变量存储在寄存器中,这样如果一个变量没有存储在内存中,那么变量上的不同核心缓存之间就没有内存同步。
所以我的 worry/question 是,如果一个原子变量被编译器优化为某个寄存器变量,那么它就不会存储在内存中,当一个核心写入它的值时,另一个核心可能会读出一个过时的值, 正确的?这个数据的一致性有没有保证?
谢谢。
您可能正在寻找这个:
[intro.progress]/18 An implementation should ensure that the last value (in modification order) assigned by an atomic or synchronization operation will become visible to all other threads in a finite period of time.
Atomic 并不像您模糊描述的那样 "solve"。它为基于顺序的内存一致性提供了某些非常具体的保证。
各种编译器在不同平台上以不同方式实现这些保证。
在 x86/64 上,没有锁用于原子整数和达到合理大小的指针。并且硬件提供了比标准要求更强的保证,使得一些更深奥的选项等同于完全一致。
我无法完全回答您的问题,但我可以为您指明正确的方向;您需要了解的主题是 "the C++ memory model".
也就是说,存在原子是为了避免您描述的确切问题。如果您要求完全的内存顺序一致性,并且线程 A 修改 X,然后修改 Y,则没有其他线程可以看到 Y 被修改但 X 看不到。C++ 标准没有指定如何提供这种保证;缓存行失效,使用特殊指令进行访问,禁止编译器进行某些基于寄存器的优化等都是编译器所做的事情。
请注意,C++ 内存模型已针对 C++17 进行了改进、错误修复和完善,以描述新并行算法的行为并允许它们在具有正确标志的 GPU 硬件(以及其他位置)上高效实施,反过来又影响了新 GPU 硬件提供的保证。所以谈论内存模型的人可能会很兴奋并且谈论比您主要关注的 C++11 问题更多的现代问题。
这是一个复杂的大话题。编写您认为可移植的代码真的很容易,但只能在特定平台上运行,或者通常只能在您测试过的平台上运行。但这只是因为线程很难。