Assembly 内存障碍对递增代码有什么影响?

Assembly 内存障碍对递增代码有什么影响?,assembly,atomic,cpu-architecture,atomicity,memory-barriers,Assembly,Atomic,Cpu Architecture,Atomicity,Memory Barriers,考虑以下程序:两个线程正在迭代同一个函数,该函数包含递增共享计数器变量的值。没有锁保护变量,因此我们谈论的是无锁编程。我们还确保线程将在不同的内核/CPU上运行。迭代次数足够大,例如N=100000 操作本身如下所示,列为伪代码。正如预期的那样,指令之间会有各种延迟,这取决于CPU执行的其他操作。下面的一个只是运行它们的一种可能方式 CPU 0 | CPU 1 ------------------------------------------

考虑以下程序:两个线程正在迭代同一个函数,该函数包含递增共享计数器变量的值。没有锁保护变量,因此我们谈论的是无锁编程。我们还确保线程将在不同的内核/CPU上运行。迭代次数足够大,例如N=100000

操作本身如下所示,列为伪代码。正如预期的那样,指令之间会有各种延迟,这取决于CPU执行的其他操作。下面的一个只是运行它们的一种可能方式

      CPU 0           |        CPU 1
------------------------------------------
  LOAD count          |
  INC count           |     LOAD count
                      |     INC count
                      |     STORE count
  STORE count         |
我们不要只针对x86体系结构,因为它的内存模型非常强大。事实上,让我们考虑一个基于McKenney C.61的内存排序恶意体系结构。 这段代码的主要问题是——毫无例外——最终结果是错误的。竞争条件将使一个CPU在另一个CPU基于相同的计数值执行相同操作的同时计算新的计数器值变得足够频繁。结果是,每个CPU将向相应的缓存线回写递增的count值,但相同。这与缓存一致性的MESI协议并不矛盾,因为每个CPU以独占方式获取缓存线并按顺序写入;唯一不幸的是,写入的是同一个计数器值

然而,我感兴趣的是设置记忆障碍的影响。排除上一段中的问题,记忆障碍没有设置到位或设置不好的事实会对该程序的工作方式产生负面影响吗

直观地考虑存储缓冲区,以及其中的值可能无法跳过或丢失的事实,它们最终必须写入缓存线。所以写障碍不会产生影响。无效队列和读取障碍是否也没有影响?我的假设正确吗?我遗漏了什么吗?

你是对的,记忆障碍不能创造原子性。他们仅命令该核心自身对其L1d缓存的访问,例如,在以后的存储或加载=完全屏障之前耗尽存储缓冲区,或在任何以后的加载和存储可以执行=轻型屏障之前等待以前的加载读取缓存。它们不会将多条指令捆绑到一个原子RMW事务中

创建原子性wrt。任何其他核心可以做的事情,您都需要这个核心将缓存线从加载到存储保持在MESI独占或修改状态。屏障不能做到这一点,您需要特殊的asm指令,如x86 lock add dword[mem],1或在许多类似RISC的机器上,如果缓存线自负载链接后未保持对此核心的独占性,则中止存储


< P>内存障碍对于C++ STD是重要的:原子,因为这也意味着订购获取、发布或SEQJCST,除非您使用MexyYORADORY轻松,在这种情况下编译器永远不会使用障碍指令。我认为内存障碍最多只会影响附近的核心和一级缓存,但也许根据系统设计,它会扩展得更深,如果没有,那么在没有锁的情况下,你总是会遇到这个问题。INC count怎么办?更具体地说,为什么会出现内存操作数?程序不能通过添加内存障碍来修复,因此程序不会因为缺少内存障碍而中断;股份有限公司;存储计数是有意义的,或者只是INC count w/o load and STORE,但是load count;INC计数;商店数量有问题。顺便说一句,没有更好或更糟的。只是有坏的/有车的或没有的。。