跳过导航链接 | |
退出打印视图 | |
Oracle Solaris Studio 12.3:OpenMP API 用户指南 Oracle Solaris Studio 12.3 Information Library (简体中文) |
用于改善 OpenMP 应用程序性能的一些常规技术如下:
将同步降至最低。
避免或尽量不使用 BARRIER、CRITICAL 段、ORDERED 区域和锁定。
使用 NOWAIT 子句可以消除冗余或不必要的屏障。例如,在并行区域末端总是有一个隐含的障碍。将 NOWAIT 添加到区域最后的 DO 中可以消除一个冗余的屏障。
使用已命名的 CRITICAL 段进行细粒度锁定。
使用显式 FLUSH 时要非常小心。刷新将造成数据高速缓存恢复到内存,而随后的数据访问可能需要从内存重新加载,从而会降低效率。
缺省情况下,空闲线程将在特定的超时期限后进入休眠状态。如果线程在超时期限结束时未找到工作,则会进入休眠状态,从而避免以其他线程为代价浪费处理器周期。缺省超时期限对于您的应用程序而言可能过短,从而导致线程过早或过晚地进入休眠状态。通常,如果应用程序在专用处理器上运行,则 SPIN 将会提供最佳的应用程序性能。如果某一应用程序与其他应用程序同时共享处理器,则缺省设置或者不使线程过久旋转的设置对于系统总处理能力来说最佳。使用 SUNW_MP_THR_IDLE 环境变量覆盖缺省超时期限,甚至可以使空闲线程永不进入休眠状态并始终处于活动状态。
尽可能在最高级别(如外部 DO/FOR 循环)执行并行化。在一个并行区域中封闭多个循环。通常,使并行区域尽可能大以降低并行化开销。例如,以下构造效率不高:
!$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
在并行区域中使用 PARALLEL DO/FOR 指令,而不是工作共享 DO/FOR 指令。与可能包含几个循环的常规并行区域相比,可以更有效地实现 PARALLEL DO/FOR。例如,以下构造效率不高:
!$OMP PARALLEL !$OMP DO ..... !$OMP END DO !$OMP END PARALLEL
而以下构造更有效:
!$OMP PARALLEL DO .... !$OMP END PARALLEL
在 Oracle Solaris 系统中,使用 SUNW_MP_PROCBIND 将线程绑定到处理器。处理器绑定与静态调度一起使用时,将有益于展示某个数据重用模式的应用程序,在该应用程序中,由并行区域中的线程访问的数据将位于上一次所调用并行区域的本地缓存中。请参见2.3 处理器绑定。
尽可能使用 MASTER,而不是 SINGLE。
MASTER 指令作为不带隐式 BARRIER 的 IF 语句来实现:IF(omp_get_thread_num() == 0) {...}
SINGLE 指令的实现方式类似于其他工作共享构造。跟踪哪个线程首先到达 SINGLE 会增加额外的运行时开销。如果未指定 NOWAIT,则存在一个隐式 BARRIER,这样效率较低。
选择适当的循环调度。
STATIC 不会造成同步开销,并且可以在数据装入高速缓存时保持数据的局域性。但是,STATIC 可能导致负载不平衡。
由于 DYNAMIC 和 GUIDED 要跟踪已经分配了哪些块,因此会发生同步开销。虽然这些调度会导致数据局域性较差,但是可以改善负载平衡。使用不同的块大小进行实验。
使用 LASTPRIVATE 时要非常小心,因为它有可能导致很高的开销。
从并行构造返回时,数据需要从专用区复制到共享存储区。
编译器代码检查哪个线程逻辑上执行最后一个迭代。这会在并行 DO/FOR 中每个块的末尾添加额外的工作。如果块数很多,开销将会增加。
使用有效的线程安全内存管理。
应用程序可以在编译器生成的代码中显式或隐式使用 malloc() 和 free(),以支持动态/可分配数组、向量化内例程等。
libc 中的线程安全 malloc() 和 free() 具有由内部锁定造成的高同步开销。可以在 libmtmalloc 库中找到更快的版本。请用 -lmtmalloc 进行链接以使用 libmtmalloc。
在数据量较少的情况下,OpenMP 并行循环可能性能不佳。使用 PARALLEL 构造中的 if 子句指示循环仅应在预期可以提高一定性能的情况下并行运行。
如果可能,请合并循环。例如,合并两个循环:
!$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
如果应用程序缺乏超出某个级别的可伸缩性,请尝试使用嵌套并行操作。有关 OpenMP 中嵌套并行操作的更多信息,请参见1.2 特殊约定。