contributed by <vic85821
>
大一大二,還沒有面對過時間量測的問題,藉這個機會一次弄懂
system time
user time
user time + system time = process takes CPU time
real time
Question
make check
time ./time_test_baseline
N = 400000000 , pi = 3.141593
3.60user 0.02system 0:03.62elapsed 100%CPU (0avgtext+0avgdata 1768maxresident)k
0inputs+0outputs (0major+84minor)pagefaults 0swaps
time ./time_test_openmp_2
N = 400000000 , pi = 3.141593
3.90user 0.00system 0:01.95elapsed 199%CPU (0avgtext+0avgdata 1584maxresident)k
0inputs+0outputs (0major+85minor)pagefaults 0swaps
time ./time_test_openmp_4
N = 400000000 , pi = 3.141593
7.24user 0.00system 0:01.95elapsed 370%CPU (0avgtext+0avgdata 1744maxresident)k
0inputs+0outputs (0major+93minor)pagefaults 0swaps
time ./time_test_avx
N = 400000000 , pi = 3.141593
1.64user 0.00system 0:01.64elapsed 99%CPU (0avgtext+0avgdata 1576maxresident)k
0inputs+0outputs (0major+83minor)pagefaults 0swaps
time ./time_test_avxunroll
N = 400000000 , pi = 3.141593
1.46user 0.00system 0:01.47elapsed 99%CPU (0avgtext+0avgdata 1788maxresident)k
0inputs+0outputs (0major+87minor)pagefaults 0swaps
double computePi_v1(size_t N)
{
double pi = 0.0;
double dt = 1.0 / N; // dt = (b-a)/N, b = 1, a = 0
for (size_t i = 0; i < N; i++) {
double x = (double) i / N; // x = ti = a+(b-a)*i/N = i/N
pi += dt / (1.0 + x * x); // integrate 1/(1+x^2), i = 0....N
}
return pi * 4.0;
}
pi 是 (
一個半徑為1的圓,面積就是
因此在一個邊長為2的正方形中間,隨機亂數產生點,圓內的點/點的總數
double compute_pi_toss(size_t N)
{
size_t sum;
for(size_t i = 0; i < N; i++)
{
double x,y,z;
x = (double)rand()/RAND_MAX;
y = (double)rand()/RAND_MAX;
z = x*x+y*y;
if (z<=1) sum++;
}
return sum/(double)N * 4.0;
}
明顯有誤差而且執行時間長
N = 400000000 , pi = 3.141574
9.84user 0.03system 0:09.87elapsed 99%CPU (0avgtext+0avgdata 1792maxresident)k
0inputs+0outputs (0major+86minor)pagefaults 0swaps
公式:
Proof:
先從黎曼積分開始
分解
但當x=1時,不在收斂半徑,需要額外證明
當n
得證##
程式碼
double compute_pi_leibniz_baseline(size_t N)
{
double pi = 0.0;
for (size_t i = 0; i < N; i++)
{
pi += pow(-1.0,i) / (2*i + 1);
}
return pi;
}
公式:
程式碼
double compute_pi_eular_baseline(size_t N)
{
double pi = 0.0;
for (size_t i = 1; i < N; i++)
{
pi += 1 / pow(i,2);
}
return sqrt(6 * pi);
}
plot sin(x) lt rgb "#FF0000"
lt
: linetypergb "#FF0000"
: 16進位的紅色編碼gnuplot程式碼
reset
set xlabel 'N'
set ylabel 'time(sec)'
set style fill solid
set key left
set grid
set title 'compute pi time'
set term png enhanced font 'Verdana,10'
set datafile separator ","
set output 'runtime.png'
plot "result_clock_gettime.csv" using 1:2 title 'baseline' with lines lt rgb "#FF0000", \
"" using 1:3 title 'openmp_2' with lines lt rgb "#FF4500", \
"" using 1:4 title 'openmp_4' with lines lt rgb "#FFD700", \
"" using 1:5 title 'avx' with lines lt rgb "#7FFF00", \
"" using 1:6 title 'avxunroll' with lines lt rgb "#0000FF"
從圖表中可以看出有一些資料會浮動
分別是 "baseline" "openmp_4"浮動現象較為明顯
在benchmark_clock_gettime.c檔案裏面,是使用clock_gettime()
來計算執行時間
int clock_gettime(clockid_t clk_id, struct timespec *tp);
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
程式中呼叫clock_gettime(CLOCK_ID,&start)
並且#define CLOCK_ID CLOCK_MONOTONIC_RAW
,什麼是CLOCK_MONOTONIC_RAW?
額外分析看看對於openMP而言,thread的數目是否會影響浮動這個現象!!
看起來只有thread=4的時候受影響較大
將95%信賴區間內的資料保留,並重新繪圖
突然發現我計算信賴區間的方法錯了,應該是N的各個值重複計算,然後再取95%信賴區間的值
Leibniz, Eular所需時間較多
程式碼
gencsv: default
for i in `seq 100 4096 250000`; do \
for j in `seq 1 1 100`; do \
printf "%d," $$i;\
./benchmark_clock_gettime $$i; \
done > result_clock_gettime.csv ; \
./confidence_interval; \
done > result_clock_gettime_refine.csv
plot: gencsv
gnuplot runtime.gb
double compute_avg(double* data, int num)
{
double sum = 0.0;
for(int i=0;i<num;++i)
sum += data[i];
return sum / num;
}
double compute_std(double avg,double* data)
{
double sum = 0.0;
for(int i=0;i<NUM_DATA;++i)
{
sum += pow(data[i]-avg,2);
}
return sqrt(sum / (double)(NUM_DATA - 1));
}
void compute_ci(double avg,double std,double* max,double* min)
{
*max = avg + 2*std;
*min = avg - 2*std;
}