2012-11-30 53 views
0

這是在F90中,但這個問題適用於任何支持OpenMP的語言。對於需要多個存儲陣列的模擬代碼結構數據的典型方式進行時間積分會(2維現在):告訴陣列的OpenMP線程部分是隻讀的

REAL, DIMENSION(imax,jmax,n_sub_timesteps) :: vars 

哪些隨後將被類似更新:

DO J = 1, jmax 
    DO I = 1, imax 
    vars(I,J,2) = func(vars(:,:,1)) 
    END DO 
END DO 

根據我的經驗,OpenMP不會實際並行化這些循環,因爲它認爲vars不是線程安全的。但對程序員來說,顯然是這樣的。

讓我們假設對於進一步的實際情況,使vars線程本地將數據複製到它太昂貴。

那麼,有沒有辦法輕輕提示(又名脅迫)OpenMP到不鎖定vars,因爲它可能不知道沒有線程依賴性問題,但實際上沒有?我知道有一些方法可以告訴它某些東西不是線程安全的並且需要鎖定,但有沒有一種方法可以指定反轉而不爲每個線程創建副本?

回答

3

看起來你錯誤的OpenMP自動並行化。我不知道進行數據鎖定,除非明確通過引入CRITICAL部分或ATOMIC語句(或在並行區域結束了REDUCTION條款)告訴因此任何OpenMP實現的。 OpenMP編譯器不要檢查您的代碼是否存在可能的數據依賴性,並阻止您並行運行 - 這完全由您決定。如果你想做不受保護的併發訪問,你可以這樣做,並且沒有啓用OpenMP的編譯器會阻止你這樣做。下面的代碼將總是產生一個並行區域,並會分佈在組中的線程之間的外環:

!$OMP PARALLEL DO PRIVATE(I) 
DO J = 1, jmax 
    DO I = 1, imax 
    vars(I,J,2) = func(vars(:,:,1)) 
    END DO 
END DO 
!$OMP END PARALLEL DO 

在另一方面,在大多數編譯器內置自動parallelisers是非常保守和謹慎,通常如果沒有程序員的明確提示,就不會並行處理像你這樣的情況。這些提示通常採用編譯器特定指令的形式(在Fortran中格式化爲註釋或在C/C++中作爲編譯指示)。例如英特爾Fortran支持!DEC$ PARALLEL指令,提示它忽略假定數據的依賴性在下面的指令循環:

!DEC$ PARALLEL 
DO J = 1, jmax 
    DO I = 1, imax 
    vars(I,J,2) = func(vars(:,:,1)) 
    END DO 
END DO 

許多編譯重用他們的OpenMP的實現和運行時庫,以實現自動並行化功能,因此通常使用OpenMP環境變量(如OMP_NUM_THREADS)來控制生成的可執行文件的運行。

如果您的並行OpenMP程序運行速度比預期慢,還有很多其他原因,主要與錯誤共享,緩存廢棄,TLB垃圾回收,內存帶寬限制,NUMA系統上的非本地內存訪問有關,加載/存儲到共享變量等等,所以它可能看起來像OpenMP是執行自動數據鎖定,但它不。