parallel for指令中,將各次迴圈分配給執行緒的操作是由系統完成的。然而,大部分openmp實現只是粗略地使用塊分割。乙個更好的分配方案是輪流分配執行緒的工作(迴圈劃分)。在迴圈劃分中,歌詞迭代**流地一次乙個地分配給執行緒。不難發現,乙個好的迭代分配能夠對效能有很大的影響。在openmp中,將迴圈分配給執行緒稱為排程,schedule子句用於在parallel for或者for指令中進行迭代分配。
schedule子句
sum=
0.0;
#pragma omp parallel for num_threads(thread_count)\
reduction(+:sum) schedule(static,1)
for(i=
0;i<=n;i++
)
一般而言,schedule子句有如下形式
schedule
([,])
type可以是以下任一種
static。迭代能夠在迴圈執行前分配給執行緒。
dynamic或guided。迭代在迴圈執行時被分配給執行緒,因此在乙個執行緒完成了它的當前迭代集合後,他能從執行時系統中請求更多。
auto。編譯器和執行時系統決定排程方式。
runtime。排程在執行時決定。
chunksize是乙個正整數。在openmp中,迭代塊是在順序迴圈中連續執行的一塊迭代語句,塊中的迭代次數是chunksize。只有static dynamic和guided排程有chunksize。
系統以輪轉的方式分配chunksize塊個迭代給每個執行緒。
假設,有12個迭代0,1,2,…,10,11和三個執行緒,如果在parallel for或for指令中
使用schedule(static,1),迭代分配如下
thread 0: 0,3,6,9
thread 1: 1,4,7,10
thread 2: 2,5,8,11
如果使用schedule(static,2),迭代分配如下:
thread 0: 0,1,6,7
thread 1: 2,3,8,9
thread 2: 4,5,10,11
如果使用schedule(static,4),迭代分配如下:
thread 0: 0,1,2,3
thread 1: 4,5,6,7
thread 2: 8,9,10,11
因此子句schedule(static,total_iterations/thread_count)就相當於被大部分openmp實現所使用的預設排程。這裡的chunksize可以被忽略,如果被忽略,就近似於total_iterations/thread_count
在dynamic排程中,迭代也被分成chunksize個連續迭代的塊,每個執行緒執行一塊,並且當乙個執行緒完成一塊時,它將從執行時系統請求另一塊,直到所有的迭代完成。chunksize可以被忽略。如果忽略了,chunksize為1.
在guided排程中,每個執行緒也執行一塊,並且當乙個執行緒完成一塊時,請求另一塊,然而,當塊完成後,新塊的大小會變小。如果沒有指定chunksize大小,那麼塊的大小為1;如果指定了,那麼快的大小就是chunksize,除了最後一塊的小大可以比chunksize小。未指定size大小(最後迭代塊大小最小會降到1)。
c同學解釋:guided指定迭代塊的最小值,迭代塊一直縮小,知道縮小到chunksize大小,所以書上面說除了最後一塊的大小可以比chunksize小。那麼每塊的大小是剩餘迴圈次數除以執行緒數,
例如20個迴圈3個執行緒,chunksize=2
chunksize為7,5,3,2,2,1先由系統決定好,但它是動態分配,這三個數字會放到乙個佇列裡,誰先做完誰先取。
環境變數是能夠被執行時系統所訪問的命名值,即他們在程式的環境中是可得的。一些經常被使用的環境變數是path,home和shell。path變數明確了當尋找乙個可執行檔案時shell應該搜尋哪些目錄。home變數指定使用者主目錄的位置,shell變數指定使用者shell的可執行位置。
當schedule(runtime)指定時,系統使用環境變數omp_schedule在執行時來決定如何排程迴圈。就相當於用乙個變數來概括所有的迴圈排程。
omp_schedule環境變數會呈現任何被static,dynamic或guided排程所使用的值。
假設在程式中有一條parallel for指令,並且它已經被schedule(runtime)修改了,那麼如果使用bash shell,就能通過執行以下命令將乙個迴圈分配所得到的迭代分配給執行緒
export omp_schedule=「static,1」;
現在,當開始執行程式時,系統將排程for迴圈的迭代,就如同使用子句schedule(static,1)修改了parallel for指令那樣。
如果需要並行化乙個for迴圈,那麼我們如何決定使用哪一種排程和chunksize的大小?
每一種schedule子句有不同的系統開銷。
guided排程開銷》dynamic排程開銷》static排程開銷
因此,如果不用schedule子句就可以達到令人滿意的效能,就需要進行多餘操作。
最優排程方式是由執行緒的個數和迭代的次數共同決定的。
如果我們斷定預設的排程方式效能低下,那麼我們會做大量的實驗來尋找最優的排程方式和迭代次數。
但在某些情況下,應該優先考慮有些排程
如果迴圈的每次迭代需要幾乎相同的計算量,那麼可能預設的排程方式能提供最好的效能。
如果隨著迴圈的進行,迭代的計算量線性遞增或遞減,那麼採用比較小的chunksize的static排程可能會提供最好的效能。
如果每次迭代的開銷實現不能確定,那麼可能需要嘗試使用多種不同的排程策略。在這種情況下,應當使用schedule(runtime)子句,通過賦予環境變數omp_schedule不同的值來比較不同排程策略下程式的效能。
《並行程式設計導論》02 openmp
global result 0.0 pragma omp parallel num threads thread count openmp提供了乙個更清晰的方法來避免local trap的序列執行 將global result定義為乙個歸約變數。歸約操作符是乙個二元操作,規約就是將相同的歸約操作符重...
《並行程式設計導論》03openmp
氣泡排序 for list length n list length 2 list length 這裡陣列a儲存n個int型整數,演算法將他們公升序排列。外部迴圈先找到列表最大元素將他存在a n 1 中,然後尋找次大的元素並存在a n 2 中,以此類推。因此,第一遍處理全部的n個元素,第二遍處理除了...
OpenMP並行程式設計(一)
openmp並行程式設計 一 openmp是乙個支援共享儲存並行設計的庫,特別適宜多核cpu上的並行程式設計。今天在雙核cpu機器上試了一下openmp並行程式設計,發現效率方面超出想象,因此寫出來分享給大家。在vc8.0中專案的屬性對話方塊中,左邊框裡的 配置屬性 下的 c c 下的 語言 頁裡,...