# 2017q1 Homework1 (compute_pi)
contributed by <`yangyang95`>
## Reviewed by `PeterTing`
* 嘗試對蒂卡羅算法進行優化,像是用 OpenMP , SIMD 等等。
* 可以嘗試計算 error rate 並進行分析。
* 可以對不同的時間函數進行研究。
* 要對圖表進行分析,不然放出來只是好看的
###### tags: `sysprog2017` `HW1` `yangyang95`
電腦規格看 [這裡](https://hackmd.io/s/HJ2c_XYKx)
github page 看 [這裡](https://github.com/yangyang95/compute-pi)
## 分析程式
N = 400000000 , pi = 3.141593
```
./time_test_baseline
3.61user 0.00system 0:03.61elapsed 99%CPU (0avgtext+0avgdata 1740maxresident)k
0inputs+0outputs (0major+79minor)pagefaults 0swaps
./time_test_openmp_2
3.78user 0.01system 0:01.90elapsed 199%CPU (0avgtext+0avgdata 1840maxresident)k
0inputs+0outputs (0major+86minor)pagefaults 0swaps
./time_test_openmp_4
7.40user 0.01system 0:01.90elapsed 390%CPU (0avgtext+0avgdata 1784maxresident)k
0inputs+0outputs (0major+86minor)pagefaults 0swaps
./time_test_avx
1.57user 0.00system 0:01.57elapsed 99%CPU (0avgtext+0avgdata 1708maxresident)k
0inputs+0outputs (0major+77minor)pagefaults 0swaps
./time_test_avxunroll
1.44user 0.00system 0:01.44elapsed 100%CPU (0avgtext+0avgdata 1832maxresident)k
0inputs+0outputs (0major+82minor)pagefaults 0swaps
```
試着做一些分析
- CPU 時間 = CPU 時脈週期 * 週期時間 = CPU 時脈週期 / 頻率
- system time : kernel mode 所花費的 CPU 時間 (e.g. system calls)
- user time : user mode 所花費的 CPU 時間
- real time : 可以看成"當程式開始時看一次手錶,結束時再看一次,兩者的時間差"
- user time + system time > real time --> multi-thread
- user time + system time < real time --> interrupt
- %CPU - CPU 使用率,可大於 100 % (多核心使用)
先來看看 **baseline 版本** 的執行時間
user time:3.61 s
system time:0.00
elapsed time:3.61 s
可以看出 real (elapsed) time = user time + system time ,是單執行緒且沒有發生中斷。
再來是 **openmp_2 版本**
user time:3.78 s
system time:0.01 s
elapsed time:1.90 s
real time < user time + system time ,果然是多執行緒程式。
**openmp_4 版本**
user time:7.40 s
system time:0.01 s
elapsed time:1.90 s
user time 相對兩個執行緒增加大約兩倍,但實際執行時間卻沒有差異。
**AVX SIMD (Single instruction, multiple data) 版本**
![](https://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/SIMD2.svg/343px-SIMD2.svg.png)
註:圖內的 PU 指的是 Process Unit
是單指令流多資料流,也就是說採用一個控制器來控制多個處理器,同時對一組資料(又稱「資料向量」)中的每一個分別執行相同的操作。
現代處理器加入 SIMD 是為了提升多媒體資料的使用效能。
由數據可以看出 CPU 使用率並沒有超過 100% ,卻能平行處理資料。是故可以觀察出 SIMD 使用的是資料平行來增加效能,而非 OpenMP 使用的任務平行。
從執行時間也可以看出同樣結論:
user time:1.57 s
system time:0.00
elapsed time:1.57 s
並沒有使用到系統時間,也就是沒有進到內核去分配執行緒。
最後,除了時間資訊跟 CPU 使用率,後面那一堆資料意味不明 XD
參考資料:
- [CPU Time](https://chi_gitbook.gitbooks.io/personal-note/content/cpu_time.html)
- [vic85821 HackMD 筆記](https://hackmd.io/s/rkgYN0P6#)
- [Understanding %CPU while running top command](http://unix.stackexchange.com/questions/145247/understanding-cpu-while-running-top-command)
- [SIMD](https://en.wikipedia.org/wiki/SIMD)
- [Data parallelism](https://en.wikipedia.org/wiki/Data_parallelism)
- [Task parallelism](https://en.wikipedia.org/wiki/Task_parallelism)
## 實驗數據繪圖
使用`$ make gencsv`來產生數據並匯入 csv 檔
```C==
gencsv: default
for i in `seq 100 100 25000`; do \
printf "%d," $$i;\
./benchmark_clock_gettime $$i; \
done > result_clock_gettime.csv
```
修改程式增加資料點,以 100 的間隔從 0 到 25000 。
再加入 gnuplot 的 script
```C==
reset
set xlabel 'N'
set ylabel 'time(sec)'
set grid
set title 'Comput pi time'
set term png enhanced font 'Verdana,10'
set datafile separator ','
set output 'runtime.png'
plot [:20100][:]'result_clock_gettime.csv' using 1:2 smooth csplines title 'baseline' lw 3, \
'' using 1:3 smooth csplines title 'openmp2' lw 3, \
'' using 1:4 smooth csplines title 'openmp4' lw 3, \
'' using 1:5 smooth csplines title 'avx' lw 3, \
'' using 1:6 smooth csplines title 'avxunroll' lw 3
```
以 cubic spline 的曲線來進行繪圖,得到以下結果:
![](https://i.imgur.com/XTDPc1g.png)
參考資料:
- [Smooth](http://gnuplot.sourceforge.net/docs_4.2/node124.html)
- [談談 gnuplot(三十九):數據平滑](http://blog.sciencenet.cn/blog-373392-528809.html)
## Monte Carlo
在 computepi.c 中加入蒙地卡羅的實作
```C==
double compute_pi_MonteCarlo(size_t N)
{
int sum = 0;
srand((unsigned)time(NULL));
for(size_t i = 0; i < N; i++) {
double x = (double)rand() / (double)RAND_MAX;
double y = (double)rand() / (double)RAND_MAX;
if((x * x + y * y) <= 1)
sum++;
}
return 4.0 * sum / N;
}
```
![](https://i.imgur.com/tNkMelq.png)
> 註:時間竟然有負的,看來時間量測的方法真的蠻重要的XD
執行蒙蒂卡羅算法來測定執行時間:
```
$ time ./time_test_monte_carlo
N = 400000000 , pi = 3.141602
./time_test_monte_carlo 9.54s user 0.00s system 99% cpu 9.546 total
```
可以看出蒙蒂卡羅耗費相當長的時間,且結果有一定程度的誤差。
參考資料:
- [Estimating Pi using Monte Carlo Simulation - youtube](https://www.youtube.com/watch?v=VJTFfIqO4TU)
- [CheHsuan HackMD 筆記](https://hackmd.io/s/BkbydgVa)