2012-02-19 29 views
2

我想實現openMP,但是像我之前的很多其他海報一樣,結果只是簡化了代碼。受到以前答案的啓發,我從#pragma omp parallel for#pragma omp task去了,希望能避免一些開銷。不幸的是,並行代碼仍然是串行速度的兩倍。從其他答案看來,正確的過程似乎取決於代碼的具體要求,這就是爲什麼我認爲我必須自己提問。使用openmp更好

第一僞代碼:

#pragma omp parallel 
{ 
#pragma omp master 
while (will be run some hundreds of millions of times) 
{ 
    for (between 5 and 20 iterations) 
    { 
     #pragma omp task 
     (something) 
    } 
    #pragma omp taskwait <- it is important that all the above tasks are completed before going on 

    (something) 

    if (something) 
    { 
     (something) 

     for (between 50 and 200 iterations) 
     { 
      #pragma omp task 
      (something) 
     } 
     #pragma omp taskwait 

     (something) 
    } 

} 
} 

只有兩個for循環可以並行,其餘的必須按正確的順序進行。我想出了將while和master指令放在while循環之外的嘗試,以減少創建團隊的開銷。

我也有點好奇我是否正確使用了taskwait - 規範說明「父任務」被擱置,直到所有的子任務都被執行完畢,但這個術語是否也適用於此,任務區域不嵌套。

任何人都可以想出一個更好的方式使用openMP,這樣我實際上可以加快速度嗎?

編輯:while循環中的每一步都依賴於前面的所有步驟,因此它們必須連續完成,並在最後進行更新。如果有人想知道,它是模擬神經網絡的「事件驅動算法」的實現。

+0

for循環的每次迭代需要多長時間?如果任務規模很小,很可能無法在這裏獲得加速。此外爲什麼'#pragma omp task'會更快,然後'#pragma omp for'?畢竟後者應該能夠以更少的管理開銷逃脫。對我來說,似乎如果速度更快,那麼您的情況可能使用了錯誤的調度模式。關於taskwait:據我瞭解,'master'部分應該是你的父任務(或者'parallel'部分,但似乎不太可能) – Grizzly 2012-02-19 19:43:49

+0

我知道任務會更快,因爲對一個老問題的回答說了些什麼「如果for循環中的迭代次數太少,則最好使用任務代替」。在序列情況下,1.7秒內可能經歷10000次while循環。考慮到其他設置,對於第二個for循環的每次迭代,球估計將爲1.0-0.5微秒。我知道它很短,但被告知我低估了並行化的力量,並決定給它一個鏡頭:) – Kaare 2012-02-19 19:54:02

+0

這聽起來好像你需要考慮新算法或新的並行處理範例,或者可能甚至兩個。 – talonmies 2012-02-19 20:07:34

回答

2

對於並行編程,您還應該設計您的問題,以便您很少需要同步您的線程。每次你同步你的線程時,你將得到所有線程中最差的性能。如果您需要同步您的線索,請嘗試重新設計您的問題,以避免這些同步。

將您的代碼從#pragma omp parallel for調整爲#pragma omp task不會讓您有任何重大改進,因爲它們的執行時間差別通常是可忽略的。在嘗試調整一些常規調用或omp語句之前,您需要將問題調整爲並行執行。您需要真正地以「並行」思考才能獲得良好的可擴展性能增長,只是適應串行代碼很少有效。

在你的代碼中,你應該嘗試parallize while循環而不是內循環。如果你將小型for循環合併,你不會得到任何顯着的性能提升。

+0

恐怕這是完全不可能的。我意識到它在上面並不明顯,但while循環中的每個迭代都依賴於前面的循環,所以它們必須按順序進行。 – Kaare 2012-02-19 19:35:10

+1

然後嘗試重新設計您的問題,以獲得獨立的循環。否則,你會浪費你的時間調整並行執行不好的代碼。 – tune2fs 2012-02-19 19:48:51

0

我不確定任務是否正確。我不熟悉任務,但似乎每次遇到#pragma omp task時都會啓動一個線程。我寧願嘗試類似:

while (will be run some hundreds of millions of time) 
{ 
#pragma omp parallel 
{ 
    for (between 5 and 20 iterations) 
    { 
     (something) 
    } 
#pragma omp single/master 
{ 

    (something) 
    bool flag = false; 
    if (something) 
    { 
     (something) 
     flag = true; 
    } 
} 

    if (flag) 
    { 
     for (between 50 and 200 iterations) 
     { 
      (something) 
     } 
    } 
#pragma omp single/master 
{ 
      (something) 
} 
    } 
    } 

同樣重要的是要記住的是,在該任務的循環可能是小的並行執行提供任何加速,因爲在啓動和同步線程的開銷。你也應該看看重寫你的程序的可能性,所以你不需要同步你的線程,你現在做了很多。我的猜測是,你的算法和工作量對於並行執行來說實際上很小,因爲它現在寫入的速度很快。

+1

這會每次迭代n次(其中n是線程數),所以確實沒有任何好處。使用任務不會啓動新線程,而是使用當前隊伍的線程,這些線程目前處於保持狀態(不完全正確但足夠接近) – Grizzly 2012-02-19 19:41:46

0

您是否記得相應地設置環境變量? OMP_NUM_THREADS = N,其中N是處理器支持的線程或核心的數量

+0

我沒有觸及環境變量,但讓「#pragma omp parallel」自己弄清楚。我的各種版本的「hello world」顯示了正確的輸出數量(2)。 – Kaare 2012-02-19 20:09:59

+0

好奇你是否嘗試在串行中運行代碼? – pyCthon 2012-02-19 20:31:26

+0

你是什麼意思?以上?是的,如果我不向g ++提供「-fopenmp」,代碼將以串行方式運行。這就是我可以說平行版太慢的原因。我是否正確理解你的問題? – Kaare 2012-02-19 20:44:55