伪共享(False Sharing)指的是什么? “伪”又表示什么是假的呢?

5 阅读2分钟

伪共享(False Sharing)是多核处理器中常见的一种性能问题,通常发生在多个线程访问同一个缓存行时,尽管这些线程访问的数据并不直接相关。这种现象会导致缓存一致性协议的频繁交互,从而导致性能下降。

为什么是“伪”共享?

“伪”共享的关键在于,多个线程操作的数据实际上并不共享有用信息,但由于它们位于同一个缓存行内,处理器会错误地认为它们之间存在共享关系。这种误解会触发缓存一致性协议(例如MESI协议)不断地进行数据同步和缓存失效,导致缓存频繁地被清空和重新加载,进而拖慢程序的运行速度。

缓存行和伪共享的机制:

  1. 缓存行(Cache Line) :现代CPU通常使用缓存来提高内存访问速度。缓存被分成多个小块,称为缓存行,通常每个缓存行大小为64字节。当一个线程访问某个内存位置时,整个缓存行(可能包含多个数据项)会被加载到缓存中。
  2. 伪共享的发生:如果不同线程操作的数据恰好位于同一个缓存行中,尽管这些数据互不相干,处理器还是会认为这些数据存在共享的可能性,导致缓存行的无效和重载。比如,两个线程分别修改缓存行内不同的变量,这时即使这些变量并不相关,缓存一致性协议也会频繁失效,造成性能下降。

举例说明:

假设有两个线程,它们分别操作数组 arr 中的两个变量 arr[0]arr[1],并且它们恰好位于同一个缓存行内。虽然这两个变量在逻辑上是独立的,但由于它们位于同一缓存行,线程1修改 arr[0] 会使得缓存行失效,线程2修改 arr[1] 时也会使缓存行失效。这样就发生了伪共享,导致了性能的浪费。

如何避免伪共享?

  1. 数据对齐:通过合适的填充或对齐,使得每个线程操作的数据位于不同的缓存行,从而避免多个线程操作同一个缓存行。
  2. Padding(填充) :可以在相关数据结构中添加额外的字节,使得每个线程访问的数据不再位于同一缓存行。例如,可以在结构体中的变量之间加入填充字节,确保每个变量都位于不同的缓存行中。

总结来说,伪共享的“伪”指的是,数据在逻辑上并不共享,但是由于存储位置的原因,导致了不必要的缓存失效,从而降低了系统的性能。