2013-10-02 67 views
1

我寫更少了以下原理計算代碼:信號中的OpenMP

#pragma omp parallel 
{ 
    #pragma omp for nowait 
    // Compute elements of some array A[i] in parallel 

    #pragma omp single 
    for (i = 0; i < N; ++i) { 
     // Do some operation with A[i]. 
     // This time it is important that operations are sequential. e.g.: 
     result = compute_new_result(result, A[i]); 
    } 
} 

兩個計算A[i]compute_new_result是相當昂貴的。所以我的想法是並行計算數組元素,並且如果任何線程獲得空閒,它就開始執行順序操作。很有可能啓動的數組元素已經被計算出來了,而其他的將由其他線程提供,並且仍然是第一個循環。

然而,爲了使這個概念的工作,我必須做到兩兩件事:

  1. 爲了讓OpenMP的分裂在另一種方式的循環,即兩個線程:線程1計算 A[0]A[2]A[4]和線程2: A[1], A[3], A[5]

  2. 提供一些信令系統。我正在考慮一組標誌,表示A[i]已經被計算出來。然後compute_new_result應該等待相應的A[i]的標誌在繼續之前被釋放。

我會很高興爲任何提示如何實現這兩個目標。我需要該解決方案可以在Linux,Windows和Mac上移植。我正在用C++ 11編寫整個代碼。


編輯:

我已經找到了答案拳頭問題。看起來好像schedule(static,1)條款已經足夠了#pragma omp for指令。

不過,我還是想對第二個問題的優雅的解決方案......

+0

做了[我]取決於所有A [J:J <我,或者只是在一些項目?這可能使我們有可能想出其他方法來實現這一目標。 – ChronoTrigger

+0

我會看看進度條款。但是,我不明白這些任務可以如何幫助信號。我需要A的特定元素的信號,而不是計算它們的線程的結束。 –

+0

A [i]依賴於A [i-1]。特別是他們是一些大矩陣,我首先需要計算,然後找到運算結果f(A [3] * f(A [2] * f(A [1] * f(A [0],I )))),其中f是一些已知函數。 –

回答

1

如果您不介意將OpenMP 替換爲工作共享結構,並使用可生成任務的循環,則可以使用OpenMP任務來實現應用程序的兩個部分。

在第一個循環中,您將創建(而不是循環塊)負責迭代的計算負載的任務。第二個循環的每次迭代也會成爲OpenMP任務。那麼重要的部分將是同步不同階段之間的任務。

對於您可以使用任務相關性(使用OpenMP 4.0引入):

#pragma omp task depend(out:A[0]) 
{ A[0] = a(); } 

#pragma omp task depend(in:A[0]) 
{ b(A[0]); } 

將確保任務完成之前任務B不運行。

乾杯, -Michael

+0

有趣。我試圖用taskwait來解決這個問題,但這似乎並不成功。 – pburka

+0

看起來很有趣。但是,我還不知道兩件事情:1. GCC是否支持OpenMP 4.0? 2.如何在循環中啓動任意數量的任務(請問'for(..){#omp task {...}}工作)?編譯時我不知道'A'的大小。 –

0

這可能是一個擴展的意見,而不是一個答案......

所以,你有一個兩階段計算。在階段1中,您可以獨立計算數組A中的每個條目。因此,使用OpenMP parallel for循環來並行化是非常簡單的。但這裏存在一個問題,對線程的單純工作分配可能會導致跨線程的(嚴重的)不平衡負載。

在第2階段有一個計算是不那麼容易並行化,哪些是你打算給第一線程完成第1階段

個人而言,我想這個分成2個階段的份額。首先,使用parallel for循環。在第二滴OpenMP中,只需要一個順序代碼。通過調整schedule子句的參數來排除階段1中的負載平衡;我會試着先嚐試schedule(guided)

如果調整日程安排無法提供您想要的餘額,請調查替換parallel fortask -ing。

不要通過滾動自己的信號技術來使第2階段的代碼複雜化。我並不擔心複雜功能會壓倒你,儘管你可能會擔心這一點,但除非你在第一階段理清負載平衡,否則複雜功能將無法帶來任何好處。當你做完這些後,不需要將phase2放入OpenMP並行區域。

+0

謝謝您的評論。這是我現在的方法,我想優化。你可能是對的,併發症是不值得的,但我必須完成程序來測試它在現實生活中以瞭解它。對不,我想要使用一個std :: mutex數組,當我計算出A [i]時,它鎖定在第一個循環的開始處並解鎖。但我仍然希望有一個更優雅的解決方案。 –