繁体   English   中英

内存屏障/栅栏的开销

[英]Overhead of a Memory Barrier / Fence

我目前正在编写C ++代码,并在我的代码中使用了很多内存屏障/围栏。 我知道,MB告诉编译器和硬件不要重新排序它周围的写/读。 但我不知道这个操作在运行时对于处理器有多复杂。

我的问题是:这种障碍的运行时开销是多少? 谷歌没有找到任何有用的答案......开销是否可以忽略不计? 或者导致MB的大量使用导致严重的性能问题?

最好的祝福。

与算术和“正常”指令相比,我理解这些指令非常昂贵,但没有数字来备份该声明。 我喜欢jalf的回答,描述了指令的效果,并想补充一点。

通常存在一些不同类型的障碍,因此理解差异可能会有所帮助。 例如在清除锁定字(例如ppc上的lwsync或ia64上的st4.rel)之前的互斥实现中需要像jalf所提到的那样的屏障。 所有读取和写入都必须完成,并且只能执行管道中稍后没有内存访问且不依赖于正在进行的内存操作的指令。

另一种类型的障碍是在获取锁时在互斥实现中使用的类型(示例,ppc上的isync或ia64上的instr.acq)。 这会对将来的指令产生影响,因此如果预取了非依赖性负载,则必须将其丢弃。 例:

if ( pSharedMem->atomic.bit_is_set() ) // use a bit to flag that somethingElse is "ready"
{
   foo( pSharedMem->somethingElse ) ;
}

如果没有获取障碍(借用ia64术语),如果在检查标记位检查完成之前,某些内容已成为寄存器,则程序可能会产生意外结果。

存在第三种类型的屏障,通常较少使用,并且需要强制存储负载排序。 这种排序强制执行指令的指令示例是,ppc(重量级同步)上的同步,ia64上的MF,sparc上的membar #storeload(即使对于TSO也是必需的)。

使用类似伪代码的ia64来说明,假设有一个

st4.rel
ld4.acq

没有mf介于两者之间没有保证负载跟随商店。 你知道st4rel之前的加载和存储是在那个商店或“后续”加载之前完成的,但是那个加载或其他未来的加载(也许是非依赖的商店?)可以潜入,早先完成,因为什么都没有阻止除此以外。

因为互斥实现很可能只在它们的实现中使用获取和释放障碍,所以我期望这样的可观察效果是锁定释放后的内存访问实际上有时可能发生在“仍处于关键部分”。

试着想一下教学的作用。 它不会使CPU在逻辑方面做任何复杂的事情,但它迫使它等到所有读写都被提交到主存储器。 因此,成本实际上取决于访问主存储器的成本(以及未完成的读/写次数)。

访问主内存通常非常昂贵(10-200个时钟周期),但从某种意义上说,这项工作必须在没有屏障的情况下完成,它可能只是通过同时执行其他指令来隐藏,所以你感觉不到这么多的成本。

它还限制了CPU(和编译器)重新安排指令的能力,因此可能存在间接成本,因为附近的指令不能交错,否则可能产生更有效的执行调度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM