contributed by <HaoTse
>
#include <immintrin.h>
,並在 Makefile 中的編譯選項加入-mavx
在 raytracing 中使用過的 OpenMP 也可以應用在 compute-pi 當中。
不過在 compute-pi 中每次迭代都會讀取 pi 值並更新 pi 值,不同次的迴圈中並不相互獨立,有兩個方法可以避免:
reduction(<op>:<variable>)
。
作業採用方法2 鄭皓澤
今日的 UNIX 系統內事實上存在兩個 time 指令,一個是系統所提供的 /usr/bin/time,這個 time 指令是 System V 版本所提供的工具,這是為了 Bourne shell 使用者所寫的工具;而另一個則是 C shell 內建指令 time。
因此
$ make check
輸出格式與直接$ time ./程式名稱
不同。鄭皓澤
#include <time.h>
#include <time.h>
#include <time.h>
編譯時連結 librt.so
gcc編譯時加入 -Wl,-lrt
選項,或連結時加入 -lrt
選項。
函式原型
int clock_gettime(clockid_t clk_id, struct timespec *tp);
struct timespec* tp
是函式回傳結果,struct timespec
宣告如下
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
精確到奈秒等級。
#include<sys/time.h>
函式原型
int gettimeofday(struct timeval*tv,struct timezone *tz )
首先直接將 Makefile gencsv 中的 for loop 改為 seq 1000 5000 1000000
,得到下圖
這張圖長的有點醜,這裡研究了 Libre Office 很久,最後直接使用 gnuplot 畫出來,如下圖
之後才發現 Libre Office 中的 Chart Type 要選 XY Scatter。鄭皓澤
注意. gnuplot 讀入 .csv檔時,","後面要加上空白或將他改為空白。鄭皓澤
在 trace benchmark_clock_gettime.c
時,發現裡面有許多 for loop 去跑計算 pi 的 function,回想起觀看廖健富學長筆記時老師提到的信賴區間,將這裡的 for loop 視為取樣,並將信賴區間紀錄起來。
計算信賴區間函式如下
double compute_ci(double *min, double *max, double data[SAMPLE_SIZE])
{
double mean = 0.0;
double std_dev = 0.0; //standard deviation
double std_err;
int i = 0;
//calculate mean value
for(i = 0; i < SAMPLE_SIZE; i++)
{
mean += data[i];
}
mean /= (double)SAMPLE_SIZE;
//calculate standard deviation
for(i = 0; i < SAMPLE_SIZE; i++)
{
std_dev += (data[i] - mean) * (data[i] - mean);
}
std_dev = sqrt(std_dev / (double)SAMPLE_SIZE);
//calculate standard deviation
std_err = std_dev / sqrt((double)SAMPLE_SIZE);
*min = mean - (1.96 * std_err);
*max = mean + (1.96 * std_err);
return mean;
}
如何使用信賴區間使得數據更好看還在研究了不少時間,當初機統應該好好學的QQ,下圖為使用信賴區間跑的成果
不過用 thread 的兩個版本還是有凸出,原因還在探討中。
目前只能看出花費時間的比較,無法比較計算出來的 pi 的正確性,因此決定再畫一張圖做比較。首先定義 pi 在 double 型態下的正確值,在<math.h>
中有定義了M_PI可以用做比較。加入以下 macro
#define compute_error(pi) ( (pi > M_PI) ? pi - M_PI : M_PI - pi)
time_test.c
中的 N 改為 1000,$ make check
後發現 AVX + unroll looping 版本仍然輸出差異比別人,至於為什麼會這樣還在思考中。原本的 baseline
算法為
證明
等號兩邊做定積分
當
故得證
將 Leibniz 公式轉成程式碼如下
double compute_pi_leibniz(size_t N)
{
double pi = 0.0;
for(size_t i = 0; i < N; i++)
{
int sign = (i % 2) ? -1 : 1;
pi += (sign / (2.0 * (double)i +1.0));
}
return pi * 4.0;
}
得到結果
HaoTse
sysprog21
compute-pi
SIMD AVX
timer
Leibniz