1. 程式人生 > >Udacity cs344Unit 3-Introduction to Parallel Programming筆記(超詳細,CUDA,並行,GPU)

Udacity cs344Unit 3-Introduction to Parallel Programming筆記(超詳細,CUDA,並行,GPU)

1.課程目標

如何分析GPU演算法的速度和效率(speed and efficiency)

三個新的基本演算法:歸約,掃描和直方圖(reduce,scan and histogram)

2.

 

3.再看之前講的例子

考慮兩件事

 

介紹幾個概念

a.步驟(step):指的是 單人!完成某特定計算(比如挖洞)所需時間

b.工作總量(total amount of work):所有參與員工完成計算量的總值

也就是,人數 * 步數 =  工作總量

 

4.談論演算法時,將討論兩個成本

a.step complexity(步驟複雜度):一共分成幾個步驟得到了最終結果,那個步驟數量

b.work complexity(工作複雜度):一共進行了多少次計算?

我們會用step complexity 或者work complexity來衡量一個演算法,而這兩個指標通常與input的大小是有關聯的

 

5.

從數學定義開始

有兩個輸入(一個數組和一個運算子)運算子要具有兩個性質:二元性和可結合性

 

 

6.

先看序列的歸約(每一個操作都依賴前一個操作)

操作次數為4次,共計4 steps

這意味著工作複雜度(與節點數目一致)和步驟複雜度(操作總次數)都是和input成正比的

 

7.並行歸約(就是想辦法給他湊成可以一同運算的,互相不依賴的——改變運算次序)結合性保證了次序改變,結果不受影響

如果只有p個處理器,需要多少步,才能處理n個輸入

8.試著編寫一下這個程式碼

 

 

 

 

 

9.   

 

舉一個現實中用到scan的例子:收支平衡(計算餘額)

你輸入一個,我得一個結果

 

9.數學描述

介紹一個概念:某個運算子的標識元素(identify element):比如“+”的identify element 是0

 

10.序列的for迴圈,n是幾就進行了多少次操作,就是多少個步驟,並行怎麼計算?

a.我們怎麼計算掃描和並行(的步驟和操作次數)

b.我們怎麼能儘量降低工作和步驟複雜度?

在這兩個小問題之前

先來看一個大問題:

在並行有這麼多種操作的前提下,我們為啥偏偏先關注掃描的並行化?

當每次只能進行一次計算的時候,是沒辦法並行的(都要依賴前面一次的結果)

但是像這類的計算,通常可以轉化成掃描的形式

當可以用掃描的方式來刻畫計算的時候,就有用啦!

因為:我們可以使掃描並行化!並且在GPU上飛快執行!

我們要做的是:找到能轉化成scan的運算模型!把問題從不適合GPU的轉化成適合GPU的

 

11.當找到模型後,怎麼實現掃描呢?

有兩種方法

a.不包含掃描(exclusive scan):計算結果中不包含當前元素

 

b.包含掃描(include scan)

把包含掃描轉化成不包含

 

12.測驗:scan的複雜度

步驟複雜度:就看最複雜的那個需要多少步驟就行了

工作複雜度:每一次運算都加起來的總和【0+1+2+...+(n-1)】

由於工作複雜度太高,所以聰明的人們又想出了兩種演算法!

 

12.Hill + Steele VS Blelloch 

a.

先看步驟複雜度,是logn(一般採用了分治思想的,複雜度都會是logn,因為砍掉了一些資料沒有切實的計算,而這裡的底數也不必在意,就像是若複雜度為n的平方,也不必在意前面的係數一樣)

工作複雜度:是這個矩形的面積,用長n乘上寬logn

 

b. 三角矩形法(想著傳手畫圖)【這個很像郭老師講的歸約和回溯啊,第一階段進行歸約,得出最後想要的結果,第二階段再去找湊成這個結果的路徑是什麼】

測試 max操作

 

看複雜度

工作量是不是也是2倍的?比logn要小嘛?

 

13.給你一點直覺,在兩個演算法分別在工作複雜度和步驟複雜度上各佔優勢時候,要怎麼選擇

a.工作多於處理器:可以犧牲步驟,換取工作量

 

b.處理器多於工作:願意犧牲工作量來換取更少的步驟(選擇步驟複雜度低的)

 

在並行演算法裡有很多的沙漏模型(比如剛剛的三角矩形演算法就是這樣):那麼我們可以在不同的階段採用不同的演算法,來保證總體執行通常,效率最高

 

14.直方圖

(就是統計介於某個段值內的實體個數)

如果我知道我的身高,想知道比我矮的有多少個,就用exclusive scan

 

15.實現過程

 

 

16.程式碼實現

線上性程式中

 

看並行的為啥會出錯:有兩個執行緒同時執行的風險

 

所以暴力簡單法不可行

 

17.看仨有效的法子

a.改成原子操作就可以啦

這種方法在bin(也就是各個段盛放的容器)個數很大是時候,會很好用。因為原子操作會限制並行度的大小

推出b

b.分本地記憶體,再歸約

不需要原子操作

 

c.先排序再歸約

 

 

 

18最終思想:由於這三種方法(沒有最好,各有利弊),所以把這三個方法分別用於不同的階段就好啦

a.大多數執行緒試圖訪問bin儲存器時候,原子操作不適用,因為會有大量執行緒處於等待之中(bin是直方圖下面的段數)

所以就先分block,因為在共享記憶體裡是不需要進行原子操作的,只有當最後合併時候,才需要進行原子操作

 

 

19.