在上一篇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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。