在上一篇OpenMP编程初步中,咱们经过矩阵乘法的例子简单展现了如何很方便地将程序中的循环体并行化。本文接着介绍OpenMP编程中常见的几种数据环境。
php
以实现如下公式为例:sql
此式相似MP2最后求相关能的一步。为了本文的方便,咱们将i指标单独拿出来,计算以下表达式,能够看做是获得每一个轨道的相关能贡献。编程
最后对E数组求和,则两式的结果相同。
数组
程序以下,其中具体计算K和T矩阵的程序未列出。
bash
!$omp parallel do schedule(static) &!$omp default(private) &!$omp shared(nval,nvir,ncen) &!$omp reduction(+:E)do a=1,nvir do b=1,nvir 计算属于ab的K和T数组 do j=1,nval do i=1,ncen E(i)=E(i)+Kab(i,j)*Tab(i,j) end do end do end doend do!$omp end parallel do
01微信
语法:app
!$omp parallel private(list)
顾名思义,出如今list中的变量将成为各线程私有的变量,每一个线程都有这些变量的私有副本。在上例中,循环指标a、b、i、j和数组Kab、Tab都是每一个线程私有的。须要注意的是,private子句声明的变量在进入并行区域时,不会继承并行区域外同名原始变量的值。
ui
02url
语法:spa
!$omp parallel shared(list)
相似地,出如今shared的列表中的变量就是公有变量,全部的线程都能访问这些变量。程序中若是出现了对公有变量的写操做,须要格外当心,比较容易出现数据竞争。
03
语法:
!$omp parallel default(private|shared|firstprivate|none)
用来指定变量的默认属性,就不用写在列表中了。例如,上例中default类型为private,那么只要没有出如今shared类型中的变量就都是private类型。通常来讲编程时先预估一下两种类型的数据哪一个多,将多的设为默认类型。
04
语法:
!$omp parallel reduction(operator:list)
在本文的示例中,在对每一个a的循环中,会算出一部分E(1:ncen)的值,而程序结束后,须要把全部a的E数组求和,才能获得最终的E数组。若是直接将E数组声明为shared类型,线程间会出现数据竞争,没法准确获得E数组的值,且每次运行的结果可能会不相同。OpenMP提供了一个reduction(归约)操做,保证每次只有一个线程更新结果,其原理是为每一个线程建立私有备份,循环结束后,对每一个线程的终值用指定的操做符进行计算,最后更新共享变量。
归约操做支持的运算符有:+、-、*、.and.、.or.、.eqv.、.neqv.、min、max、iand、ior、ieor。
在Fortran中支持数组的总体操做,所以变量列表中也能够是数组,如本例。
05
语法:
!$omp parallel firstprivate(list)
前面提到,private类型的变量是不会继承进入并行区域前的数值的,若是须要继承的话,则用firstprivate来实现。
06
语法:
!$omp parallel lastprivate(list)
与firstprivate相对,若是在退出并行区域后,须要将私有变量的值传给并行区域后面的同名变量,则用lastprivate来实现。此时要注意,因为私有变量在每一个线程上都有副本,那么是谁的值传出来呢?OpenMP规定是执行最后一个循环的线程的副本传出来。例如do i=1,100这个循环中,是将i=100时的变量传出。
07
语法:
!$omp threadprivate(/comm/,a,...)
上面介绍的private子句将变量指定为私有变量后,若是退出了并行区域就会消失,而使用threadprivate子句将全局变量指定为私有变量后,能够在先后多个并行区域之间保持连续性。以下图所示:
要注意的是threadprivate语句必须紧跟变量声明,并写在主程序以前。变量列表中能够写common块的名称,也能够写具体的变量。
08
语法:
!$omp parallel copyin(list)
对具备threadprivate属性的变量,在进入某个并行区域时,能够用copyin子句将每一个线程中的值设置为与主线程中的值相等。
09
语法:
!$omp singleread(*,*) a!$omp end single copyprivate(a)
上面一段代码通常出如今某个并行区域内,只由一个线程去执行,且是随机肯定的。离开single结构后,copyprivate子句会将变量的值广播到并行区域内的其余线程的同名变量。
本文分享自微信公众号 - 量子化学(quantumchemistry)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。