Professional Documents
Culture Documents
目標
作業說明 ﴾/s/rJARexQT﴿
學習透過離散微積分求圓周率
程式碼分析
__attribute__((unused))
在編譯的時候,如果編譯器發現我們有宣告一個變數但從未使用到該變數,則編譯器會發出警告,
但此用法是告訴編譯器說,即使未引用到此變數也不要發出warning
Performance量測方法
time指令
實作
打算用Leibniz、Euler和 Monte Carlo method 等三種方法來求Pi並做比較,而且實作各種加速版本
multi‐thread
SIMD
﴾https://i.imgur.com/IqtF8Aa.png﴿
上述表示式可以縮減成下方公式
﴾https://i.imgur.com/Sd9lPYX.png﴿
接下來就用C語言來實作看看囉
double compute_pi_leibniz(size_t N)
{
double pi = 0.0;
for(size_t i = 0; i < N; i++) {
double denominator = (2 * i) + 1;
double numerator = pow(‐1, i);
pi = pi + (numerator / denominator);
}
return pi * 4.0;
}
Perf分析Leibniz法算PI
﴾https://i.imgur.com/oO3rEQO.png﴿
效能卡在算‐1的N次方上了
改進
用更簡單的方法算pow﴾‐1, i﴿
因為只是很規律的1,‐1,1,‐1,1,…
所以用一個三元運算子就可以取代上述功能
double numerator = (i % 2 == 0 ? 1 : ‐1);
﴾https://upload.wikimedia.org/wikipedia/commons/8/84/Pi_30K.gif﴿
原理
假設我們有一個圓形的半徑為1,那它的面積即為π,四分之一個圓面積為π/4,利用一個邊長為1的
正方形將此四分之一圓包圍起來,在這個正方形範圍內大量產生亂數座標,落在這個四分之一圓的
機率應該為趨近於π/4﴾落在四分之一圓之內和之外的機率和面積成正向關係﴿
我們可以用下列公式來表示
π/4 : 1 = S : N
S為落入四分之一圓內座標個數,N為產生亂數次數,轉換一下
π = 4 * ﴾S / N﴿
https://hackmd.io/s/BkbydgVa 3/9
9/29/2016 2016q3 Homework1 (computepi) HackMD
實作看看吧
double compute_pi_montecarlo(size_t N)
{
double pi = 0.0;
size_t sum = 0;
srand(time(NULL));
for (size_t i = 0; i < N; i++) {
double x = (double) rand() / RAND_MAX;
double y = (double) rand() / RAND_MAX;
if ((x * x + y * y) < 1) {
sum++;
}
}
pi = 4 * ((double)sum / N);
return pi;
}
這邊補充一下亂數產生的主要兩種方法
./time_test_montecarlo_pthread & sudo perf top ‐p $!
https://hackmd.io/s/BkbydgVa 4/9
9/29/2016 2016q3 Homework1 (computepi) HackMD
﴾https://i.imgur.com/c7924fm.png﴿
可以看出來大部份的時間﴾80%﴿都花在產生random的座標點位上,應該就是我們的效能瓶頸了
改進的方法
使用pthread﴾multi‐thread﴿方式來加速運算
使用cuRAND來平行產生亂數 ﴾http://cs.umw.edu/~finlayson/class/fall14/cpsc425/notes/23‐cuda‐random.html﴿
並用cuda來計算
不要用rand﴾﴿方法產生亂數?
實驗數據
原始版
https://hackmd.io/s/BkbydgVa 5/9
9/29/2016 2016q3 Homework1 (computepi) HackMD
﴾https://i.imgur.com/kNhaylz.png﴿
Leibniz和Monte Carlo
有時使用openMP 4個thread的時間會大於不使用多執行緒的時間,不是很穩定
pthread版
﴾https://i.imgur.com/oNnY26T.png﴿
cuda版
https://hackmd.io/s/BkbydgVa 6/9
9/29/2016 2016q3 Homework1 (computepi) HackMD
cuda版
最近開始學cuda,想說就拿來應用看看,以下是寫CUDA的基本流程
﴾https://i.imgur.com/ZjyNcoo.png﴿
列出我用的GPU訊息
https://hackmd.io/s/BkbydgVa 7/9
9/29/2016 2016q3 Homework1 (computepi) HackMD
Device 0 Name: GeForce GT 650M
Total global memory: 2147287040
Total shared memory per block: 49152
Total registers per block: 65536
Warp size: 32
Maximum memory pitch: 2147483647
Maximum threads per block: 1024
Maximum dimension 0 of block: 1024
Maximum dimension 1 of block: 1024
Maximum dimension 2 of block: 64
Maximum dimension 0 of grid: 2147483647
Maximum dimension 1 of grid: 65535
Maximum dimension 2 of grid: 65535
Clock rate: 950000
Total constant memory: 65536
Texture alignment: 512
Concurrent copy and execution: Yes
Number of multiprocessors: 2
Kernel execution timeout: Yes
﴾https://i.imgur.com/DbHrlEW.png﴿
用GPU就是猛!
https://hackmd.io/s/BkbydgVa 8/9
9/29/2016 2016q3 Homework1 (computepi) HackMD
﴾https://i.imgur.com/FwiwUn1.png﴿
在GPU版本中,根據N值不同,我使用到的block數也不同,但每個block內的thread數是固定為
500,每一個thread都會跑固定迴圈數,迴圈裡使用cuRAND產生亂數,並且計算在四分之一圓內的
點位數。
這樣一來,gpu已經把最繁重的部份解決掉,cpu只要把每個thread算出來的加總再總加總一次算機
率就可以了。
接下來的課題就是如何更自動化分配block數量和thread數量和分析帶來的效能影響
GitHub
https://github.com/CheHsuan/compute‐pi ﴾https://github.com/CheHsuan/compute‐pi﴿
參考
[1]cuRAND範例 http://cs.umw.edu/~finlayson/class/fall14/cpsc425/notes/23‐cuda‐random.html
﴾http://cs.umw.edu/~finlayson/class/fall14/cpsc425/notes/23‐cuda‐random.html﴿
[2]亂數產生器wiki https://en.wikipedia.org/wiki/Random_number_generation
﴾https://en.wikipedia.org/wiki/Random_number_generation﴿
https://hackmd.io/s/BkbydgVa 9/9