Sun Studio 12:OpenMP API 用户指南

第 6 章 性能注意事项

拥有正确且可执行的 OpenMP 程序之后,应该考虑其整体性能。您可以利用一些常规技术和 Sun 平台专有技术来改善 OpenMP 应用程序的效率和可伸缩性。我们将在此进行简单地介绍。

有关其他信息,请参见由 Rajat Garg 和 Ilya Sharapov 合著的《Techniques for Optimizing Applications: High Performance Computing》,该书可从 http://www.sun.com/books/catalog/garg.xml 上获得。

此外,有关 OpenMP 应用程序的性能分析和优化方面的参考文章和案例研究,请访问 Sun 开发人员门户网站,网址是 http://developers.sun.com/prodtech/cc/

6.1 一般性建议

以下技术是用于改善 OpenMP 应用程序性能的一些常规技术。


此构造效率较低:

!$OMP PARALLEL
  ....
  !$OMP DO
    ....
  !$OMP END DO
  ....
!$OMP END PARALLEL

!$OMP PARALLEL
  ....
   !$OMP DO
     ....
   !$OMP END DO
  ....
!$OMP END PARALLEL

此构造效率较高:

!$OMP PARALLEL
  ....
  !$OMP DO
    ....
  !$OMP END DO
  .....

  !$OMP DO
    ....
  !$OMP END DO

!$OMP END PARALLEL

此构造效率较低:

!$OMP PARALLEL
  !$OMP DO
    .....
  !$OMP END DO
!$OMP END PARALLEL

此构造效率较高:

!$OMP PARALLEL DO
   ....
!$OMP END PARALLEL

将以下两个循环


!$omp parallel do
  do i = ...

statements_1


  end do
!$omp parallel do
  do i = ...

statements_2


  end do

合并为一个循环


!$omp parallel do
  do i = ...

statements_1

statements_2


  end do

6.2 伪共享及其避免方法

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

6.2.1 什么是伪共享

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

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

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

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

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

6.2.2 减少伪共享

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

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

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

6.3 Solaris OS 调优特性

从 Solaris 9 发行版开始,操作系统为 SunFireTM 系统提供了可伸缩性和较高的性能。在 Solaris 9 操作系统中引入了新的特性,这些特性无需进行硬件升级即可提高 OpenMP 程序性能,这些特性包括内存定位优化 (Memory Placement Optimization, MPO) 和多页大小支持 (Multiple Page Size Support , MPSS)。

MPO 使操作系统可以将页面分配到访问这些页面的处理器附近。SunFire E20K 和 SunFire E25K 系统在相同的 UniBoardTM 内(与不同的 UniBoard 之间相比)有不同的内存延时。称为初次接触的缺省 MPO 策略在包含第一次接触内存的处理器的 UniBoard 上分配内存。对于大部分数据访问是针对每个处理器(处于初次接触定位状态)的局部内存的应用程序,初次接触策略可以显著提高该应用程序的性能。与内存平均分布在系统上的随机内存定位策略相比,此策略即可以降低应用程序的内存延迟,又能提高带宽,从而获得更高的性能。

从 Solaris 9 操作系统发行版开始,系统支持 MPSS 功能,且程序可以利用该功能对虚拟内存的不同区域使用不同的页面大小。缺省 Solaris 页面大小相对较小(在 UltraSPARC 处理器上为 8KB,在 AMD64 Opteron 处理器上为 4KB)。通过使用较大的页面大小,过多发生 TLB 未命中情况的应用程序可以提高性能。

使用 Sun 性能分析器可以测量 TLB 未命中次数。

使用以下 Solaris 操作系统命令可以获取特定平台的缺省页面大小:/usr/bin/pagesize。在此命令中使用 -a 选项可列出所有受支持的页面大小。(有关详细信息,请参见 pagesize(1) 手册页。)

有三种方法可更改应用程序的缺省页面大小: