大多数CPU架构都会对存储加载操作进行重新排序,但是我的问题是为什么?我对存储负载障碍的解释如下:
x = 50;
store_load_barrier;
y = z;
此外,与释放和获取语义相比,我看不出在无锁编程中如何使用此障碍。
简短答案:存储负载屏障可防止处理器推测性地执行存储负载屏障之后的LOAD,直到之前的所有存储都已完成。
详细资料:
存储负载屏障之所以昂贵,是因为它阻止了跨屏障对LOAD和STORE操作进行重新排序。
假设您的指令序列如下所示:
... ;; long latency operation to compute r1
ST r1, [ADDR1] ;; store value in r1 to memory location referenced by ADDR1
LD r3, [ADDR2] ;; load r3 with value in memory location ADDR2
... ;; instructions that use result in r3
执行此序列时,的值r1
将是需要很长时间才能完成的操作的结果。该指令ST r1, [ADDR1]
将不得不停顿直到r1
被读取。同时,LD r3, [ADDR2]
如果它们与先前的存储无关,则乱序处理器可以推测性地执行和其他指令。他们实际上不会提交,直到提交了存储,但是通过推测性地完成大多数工作,结果可以保存在重新排序缓冲区中,并可以更快地进行提交。
这对单处理器系统有效,因为CPU可以检查ADDR1和ADDR2之间是否存在依赖关系。但是在多处理器系统中,多个CPU可以独立执行加载和存储。可能有多个处理器正在执行ST至ADDR1和ADDR2的LD。如果CPU能够推测性地执行这些似乎没有依赖性的指令,那么不同的CPU可能会看到不同的结果。我认为以下博客文章很好地说明了这种情况如何发生(我认为在这个答案中我不能对此进行简要总结)。
现在考虑具有存储负载障碍的代码序列:
... ;; long latency operation to compute r1
ST r1, [ADDR1] ;; store value in r1 to memory location referenced by ADDR1
ST_LD_BARRIER ;; store-load barrier
LD r3, [ADDR2] ;; load r3 with value in memory location ADDR2
... ;; instructions that use result in r3
这将防止LD r3, [ADDR2]
推测性地执行该指令和随后的从属指令,直到之前的存储指令完成为止。并且这可能会降低CPU性能,因为即使在CPU本身中LD和ST之间没有依赖关系,在等待ST指令完成时整个CPU管道也可能会停顿。
可以做一些事情来限制CPU必须停止的数量。但最重要的是,存储负载屏障在负载和存储之间创建了其他依赖关系,这限制了CPU可以执行的推测执行量。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句