這並不是那麼容易做到這一點自動。 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
指令中的語句和構造中,這些指令沒有帶來任何加速。其他編譯器可能會以不同方式實現,但如果要實現便攜性能,則最好避免使用它。
如果您仍然在上面 - 不要在'workshare'中使用'FORALL'。請參閱下面更新的答案。 – 2012-07-25 06:19:36