Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 记忆、秩序、放松和可视性_C++_Atomic_Cpu Architecture_Stdatomic - Fatal编程技术网

C++ 记忆、秩序、放松和可视性

C++ 记忆、秩序、放松和可视性,c++,atomic,cpu-architecture,stdatomic,C++,Atomic,Cpu Architecture,Stdatomic,考虑两个线程T1和T2,它们分别存储和加载原子整数a_i。让我们进一步假设在开始执行加载之前执行存储。我指的是绝对意义上的时间 T1 T2 // other_instructions here... // ... a_i.store(7, memory_order_relaxed) // other instructions here // other instructions here

考虑两个线程T1和T2,它们分别存储和加载原子整数a_i。让我们进一步假设在开始执行加载之前执行存储。我指的是绝对意义上的时间

T1                                    T2
// other_instructions here...         // ...
a_i.store(7, memory_order_relaxed)    // other instructions here
// other instructions here            // ...
                                      a_i.load(memory_order_relaxed)
                                      // other instructions here
是否保证T2在加载后看到值7

是否保证T2在加载后看到值7

记忆顺序在这里是不相关的;原子操作是原子的。只要您确保写入“发生在”读取之前(您在问题的前提中声明为true),并且没有其他干预操作,T2将读取T1写入的值。这是原子操作的本质,内存顺序不会修改这一点

内存命令控制的是,如果T2看到7(是否确保“之前发生”),它是否可以访问T1在将7存储到原子中之前修改的其他数据。在
放松的
内存顺序下,T2没有这样的保证


注意:您的问题已从一种情况,即当商店处于某个状态时,您的问题已变为一种更加模糊的情况。就C++对象模型而言,没有绝对时间。特定原子对象上的所有原子操作都是按顺序进行的,但除非有某种东西在两个加载之间显式地创建了“before/after”关系,否则无法知道加载了什么值。这将是两种可能性中的一种,但哪一种不为人所知

是否保证T2在加载后看到值7

记忆顺序在这里是不相关的;原子操作是原子的。只要您确保写入“发生在”读取之前(您在问题的前提中声明为true),并且没有其他干预操作,T2将读取T1写入的值。这是原子操作的本质,内存顺序不会修改这一点

内存命令控制的是,如果T2看到7(是否确保“之前发生”),它是否可以访问T1在将7存储到原子中之前修改的其他数据。在
放松的
内存顺序下,T2没有这样的保证


注意:您的问题已从一种情况,即当商店处于某个状态时,您的问题已变为一种更加模糊的情况。就C++对象模型而言,没有绝对时间。特定原子对象上的所有原子操作都是按顺序进行的,但除非有某种东西在两个加载之间显式地创建了“before/after”关系,否则无法知道加载了什么值。这将是两种可能性之一,但哪一个是不可知道的。< / P> < P>(我回答了最新的问题;Nicol回答了C++中的“后”“之前发生”的原始问题。术语,包括同步,这意味着读者可以保证看到作者的素材,而不是在循环的锁定步进循环中运行;C++没有任何“循环”的概念。 我回答了C++如何在普通的现代CPU上运行。当然,ISO C++不涉及CPU体系结构,除了提到普通硬件有一个连贯的高速缓存,在注释中,关于C++中的<代码>原子< /代码>一致性保证的目的。 我指的是绝对意义上的时间

T1                                    T2
// other_instructions here...         // ...
a_i.store(7, memory_order_relaxed)    // other instructions here
// other instructions here            // ...
                                      a_i.load(memory_order_relaxed)
                                      // other instructions here
如果您的意思是存储在加载执行之前变得全局可见,那么根据定义,加载将看到它。但是,如果您是指正常计算机体系结构意义上的“执行”,那么不,不能保证。如果存储同时在不同的内核上运行,则其他线程需要一些时间才能看到它们

现代CPU,因此执行可以是推测性的,无序的exec,而不会在内核外看到混乱,因此执行不必在缓存未命中存储上暂停。缓存是一致的;您无法从中读取“过时”的值,但要使存储对其他内核可见需要一些时间。(在计算机体系结构术语中,存储通过将数据+地址写入存储缓冲区来“执行”。当它从存储缓冲区提交到L1d缓存时,在已知它是非推测性的之后,它变得全局可见。)

核心需要先获得缓存线的独占所有权,然后才能对其进行修改(MESI独占或修改状态),因此当需要将存储从存储缓冲区提交到L1d缓存时,如果它尚未拥有缓存线,则会发送RFO(读取所有权)。在内核看到该RFO之前,它可以让负载读取该行(即“执行”负载-注意,在高性能CPU中,负载和存储是根本不同的,内核希望尽早获得负载数据,但延迟进行存储)

相关:如果线程1以后也进行了一些加载,那么存储缓冲区也是获得存储加载重新排序的方式,即使是在一个顺序很强的CPU上,它也会保持其他所有东西的顺序。或者在一个具有像x86这样的强有序内存模型的CPU上,除了存储缓冲区之外,所有事情都是按程序顺序发生的

内存障碍只是命令这个核心的操作wrt。例如,一个完整的屏障会阻止后续加载的执行,直到先前的存储+加载已经执行,并且存储缓冲区已经耗尽到屏障的点,因此它只包含后续加载(如果有的话)

屏障对另一个核心是否看到存储没有影响,除非前提是另一个核心已经看到其他存储。然后使用屏障(或等效的释放/获取),您可以保证另一个核心也可以在发布存储之前看到其他所有内容


Jeff Preshing的访问远程服务器是一种有用的模式:您可以订购自己的操作