内存栅栏是否会降低所有CPU内核的速度?

时间:2014-09-13 09:43:09

标签: c++ c cpu atomic memory-fences

在某个地方,有一次我读到有关内存栅栏(障碍物)的信息。据说内存栅栏会导致多个CPU内核之间的缓存同步。

所以我的问题是:

  1. 操作系统(或CPU本身)如何知道需要同步哪些内核?

  2. 是否同步所有CPU内核的缓存?

  3. 如果回答(2)是“是”'并假设同步操作不便宜,使用内存栅栏会减慢我的应用程序未使用的内核吗?例如,如果我在8核CPU上运行单线程应用程序,它是否会降低CPU的所有其他7个内核的速度,因为某些缓存行必须与所有这些内核同步?

  4. 上述问题是否完全无知,围栏的工作方式完全不同?

3 个答案:

答案 0 :(得分:8)

  1. 操作系统不需要知道,并且每个CPU核心都按照它所说的去做:每个带有内存栅栏的核心必须在之前或之后进行某些操作,这就是全部。核心不能与"同步。其他内核,它相对于自身同步内存访问。
  2. 一个核心中的栅栏并不意味着其他核心与它同步,因此通常你会有两个(或更多)栅栏:一个在编写器中,一个在读卡器中。在一个核心上执行的栅栏不需要影响任何其他核心。当然,一般来说无法保证这一点,只是希望理智的架构不会过度序列化多核执行。

答案 1 :(得分:5)

通常,内存防护用于订购本地操作。以伪编译器代码为例:

load A
load B

许多CPU不保证在A之后确实加载了B,B可能位于由于某些其他内存负载而先前加载到高速缓存中的高速缓存行中。如果你引入围栏,

load A
readFence
load B

你有保证在A之后从内存加载B.如果B在缓存中但比A早,则会重新加载。

商店的情况与其他方式相同。与

store A
store B
某些CPU可能决定在写入A之前将B写入内存。同样,可能需要在两个指令之间建立一个范围来强制执行操作的排序。是否需要内存栅栏总是取决于架构。


通常,您成对使用内存栅栏:

  • 如果一个线程想要发布一个对象,它首先构造该对象,然后在将指向对象的指针写入公知位置之前执行写入栅栏。

  • 想要接收对象的线程从公知的内存位置读取指针,然后执行读取栅栏以确保基于该指针的所有进一步读取实际上给出了发布线程所期望的值。

如果缺少任何围栏,读者可以在初始化之前读取对象的一个​​或多个数据成员的值。疯狂随之而来。

答案 2 :(得分:1)

如果您说八个内核,并且每个内核都在做不同的事情,那么这些内核将无法访问相同的内存,并且在高速缓存行中也不会有相同的内存。

如果内核#1使用内存网,但没有其他内核访问内核#1访问的内存,那么其他内核根本不会被放慢速度。但是,如果核心#1写入位置X,使用内存栅栏,则核心#2尝试读取相同的位置X,内存栅栏将确保核心#2丢弃位置X的值(如果它在缓存,并从RAM中读取数据,获取核心#1写入的相同数据。这当然需要时间,但这就是记忆围栏的用途。

(如果核心共享一些缓存,则不是从RAM读取,而是从缓存中读取数据。)