《並行程式設計導論》04openmp

2021-10-02 18:30:55 字數 2861 閱讀 1142

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 下的 語言 頁裡,...