2012-07-18 43 views
7

fortran 2008 do concurrent構造是一個do循環,告訴編譯器沒有迭代影響任何其他循環。因此可以安全地並行化。並行化fortran 2008系統地「併發」,可能與openmp

有效例如:

program main 
    implicit none 
    integer :: i 
    integer, dimension(10) :: array 
    do concurrent(i= 1: 10) 
    array(i) = i 
    end do 
end program main 

其中迭代可以以任何順序進行。你可以閱讀更多關於它here

據我所知,gfortran並不會自動並行處理這些do concurrent循環,而我記得有關這樣做的gfortran-diffusion-list郵件(here)。它只是將它們轉換爲經典的do循環。

我的問題:你知道一種系統並行do concurrent循環?例如用系統 openmp語法?

+1

如果您仍然在上面 - 不要在'workshare'中使用'FORALL'。請參閱下面更新的答案。 – 2012-07-25 06:19:36

回答

12

這並不是那麼容易做到這一點自動。 DO CONCURRENT結構有一個所有頭文件這意味着它可以接受多個循環,索引變量定義和掩碼。基本上,需要更換:

DO CONCURRENT([<type-spec> :: ]<forall-triplet-spec 1>, <forall-triplet-spec 2>, ...[, <scalar-mask-expression>]) 
    <block> 
END DO 

與:

[BLOCK 
    <type-spec> :: <indexes>] 

!$omp parallel do 
DO <forall-triplet-spec 1> 
    DO <forall-triplet-spec 2> 
    ... 
    [IF (<scalar-mask-expression>) THEN] 
     <block> 
    [END IF] 
    ... 
    END DO 
END DO 
!$omp end parallel do 

[END BLOCK] 

(東西方括號中是可選的,基於相應的部件在forall的報頭存在下)

請注意,這不會像並行化一個大循環與<iters 1>*<iters 2>*...獨立迭代一樣有效,這是DO CONCURRENT預計會執行的操作。還要注意,所有頭文件都允許type-spec,它允許在頭文件中定義循環索引,並且需要圍繞BLOCK ... END BLOCK構造中的所有內容來保留語義。您還需要檢查scalar-mask-expr是否存在於所有標題的末尾,如果存在,您還應該將該IF ... END IF置於最內層循環中。

如果您只有DO CONCURRENT正文內的陣列分配,您還可以將其轉換爲FORALL並使用workshare OpenMP指令。這將比上述更容易。

DO CONCURRENT <forall-header> 
    <block> 
END DO 

將成爲:

!$omp parallel workshare 
FORALL <forall-header> 
    <block> 
END FORALL 
!$omp end parallel workshare 

鑑於上述所有,我能想到的唯一系統方式是系統經過你的源代碼,搜索DO CONCURRENT系統根據報頭和循環體的內容,用上述轉換的構造之一替換它。

編輯:目前不鼓勵使用OpenMP workshare指令。事實證明,至少英特爾Fortran編譯器和GCC在編譯期間通過將它們與OpenMP single指令一起包含在OpenMP workshare指令中的語句和構造中,這些指令沒有帶來任何加速。其他編譯器可能會以不同方式實現,但如果要實現便攜性能,則最好避免使用它。

+0

感謝您的更新。你有一個消息來源來解讀這種沮喪的行爲嗎? – max 2012-07-25 09:58:20

+0

使用GCC,您可以查看[源代碼](http://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch/gcc/fortran/)。一些結構是平行的,例如,數組賦值,但是'FORALL'不在其中。使用其他編譯器,您可以查看彙編輸出。 – 2012-07-25 11:12:43

+0

我還應該補充說,編譯器供應商實際上正在解決完全相同的問題,你正試圖解決:) – 2012-07-25 11:20:14

1

我不確定你的意思是「系統地並行化併發循環的一種方式」。然而,簡單地parallelise普通do循環使用OpenMP你可以只使用類似:

!$omp parallel private (i) 
!$omp do 
do i = 1,10 
    array(i) = i 
end do 
!$omp end do 
!$omp end parallel 

這是你所追求的?

+0

對不起,「系統」。作爲一個例子,我可以_grep_或_awk_'做併發'; XX; 'end do'代碼中的任何地方,並將它替換爲(例如_sed_或_awk_),並始終使用相同的openmp語法。不應該是事件特定的(但當然是循環變量)。 你的回答可能會以這種方式提供幫助,但它對於'do concurrent'和'end do'之間的各種東西總是正確的語法嗎? – max 2012-07-19 05:57:44

+0

據我所知,這應該是足夠的,考慮到可以進入'做併發'構造的限制 - 希望有更多的知識可以在這裏掛鐘。我對你想要做的一點擔心的是,當使用'do concurrent'構造時,編譯器將檢查你在構造中做什麼是由Fortran標準允許的,但是如果你sed/awk等。所以,如果你犯了一個錯誤,這個簡單的翻譯可能不合適,並可能導致意想不到的結果,這可能很難追查。 – Chris 2012-07-19 08:40:54