Sun Studio 12 Update 1:OpenMP API 用户指南

7.2 伪共享及其避免方法

如果不慎将共享内存结构与 OpenMP 应用程序一起使用,可能导致性能下降且可伸缩性受限制。多个处理器更新内存中相邻共享数据将导致多处理器互连的通信过多,因而造成计算序列化。

7.2.1 什么是伪共享

大多数高性能处理器(如 UltraSPARC 处理器)在 CPU 的低速内存和高速寄存器之间插入一个高速缓存缓冲区。访问内存位置时,会使包含所请求内存位置的一部分实际内存(缓存代码行)被复制到高速缓存中。随后可能在高速缓存外即可满足对同一内存位置或其周围位置的引用,直至系统决定有必要保持高速缓存和内存之间的一致性。

然而,同时更新来自不同处理器的相同缓存代码行中的单个元素会使整个缓存代码行无效,即使这些更新在逻辑上是彼此独立的。每次对缓存代码行的单个元素进行更新时,都会将此代码行标记为无效。其他访问同一代码行中不同元素的处理器将看到该代码行已标记为无效。即使所访问的元素未被修改,也会强制它们从内存或其他位置获取该代码行的较新副本。这是因为基于缓存代码行保持缓存一致性,而不是针对单个元素的。因此,互连通信和开销方面都将有所增长。并且,正在进行缓存代码行更新的时候,禁止访问该代码行中的元素。

这种情况称为伪共享。如果此情况频繁发生,OpenMP 应用程序的性能和可伸缩性就会显著下降。

在出现以下所有情况时,伪共享会使性能下降。

请注意,在循环中只读状态的共享数据不会导致伪共享。

7.2.2 减少伪共享

在执行应用程序时,对占据主导地位的并行循环进行仔细分析即可揭示伪共享造成的性能可伸缩性问题。通常可以通过以下方式减少伪共享

在特定情况下,如果处理较大的问题而共享较少,可能较难看到伪共享的影响。

处理伪共享的方法与特定应用程序紧密相关。在某些情况下,更改数据的分配方式可以减少伪共享。在其他情况下,通过更改迭代到线程的映射,为每个线程的每个块分配更多的工作(通过更改 chunksize 值),也可以减少伪共享。