2016-12-28 83 views
1

在我的C程序中,我正在計算運行Windows 10 Home的64位Intel Corei5-2410M Sandy Bridge機器上的時鐘週期數,但有些奇怪。我使用Code :: Blocks(CB)16.01在發佈版本中編譯-O2和-O3程序。對於-O2時鐘週期可以,但-O3會返回0個週期。目前,我沒有考慮渦輪增壓和超線程技術,但是以後肯定會禁用它們。如何使用Windows 10中的Code :: Blocks 16.01在-O3處計數時鐘週期?

我用下面的命令編譯

mingw32-gcc.exe -Wall -O2 -m32 -IC:\GMP\include -c "E:\abc\main.c" -o obj\Release\main.o 
mingw32-gcc.exe -Wall -O3 -m32 -IC:\GMP\include -c "E:\abc\main.c" -o obj\Release\main.o 

我們有

void schoolbook_9(int32_t *X, int32_t *Y, int64_t *Z){ 
Z[0] = (int64_t)X[0]*Y[0] + (int64_t)X[1]*Y[1] + (int64_t)X[2]*Y[2] + (int64_t)X[3]*Y[3] + (int64_t)X[4]*Y[4] + (int64_t)X[5]*Y[5] + (int64_t)X[6]*Y[6] + (int64_t)X[7]*Y[7] + (int64_t)X[8]*Y[8]; 
Z[1] = (int64_t)X[9]*Y[0] + (int64_t)X[0]*Y[1] + (int64_t)X[1]*Y[2] + (int64_t)X[2]*Y[3] + (int64_t)X[3]*Y[4] + (int64_t)X[4]*Y[5] + (int64_t)X[5]*Y[6] + (int64_t)X[6]*Y[7] + (int64_t)X[7]*Y[8]; 
Z[2] = (int64_t)X[10]*Y[0] + (int64_t)X[9]*Y[1] + (int64_t)X[0]*Y[2] + (int64_t)X[1]*Y[3] + (int64_t)X[2]*Y[4] + (int64_t)X[3]*Y[5] + (int64_t)X[4]*Y[6] + (int64_t)X[5]*Y[7] + (int64_t)X[6]*Y[8]; 
Z[3] = (int64_t)X[11]*Y[0] + (int64_t)X[10]*Y[1] + (int64_t)X[9]*Y[2] + (int64_t)X[0]*Y[3] + (int64_t)X[1]*Y[4] + (int64_t)X[2]*Y[5] + (int64_t)X[3]*Y[6] + (int64_t)X[4]*Y[7] + (int64_t)X[5]*Y[8]; 
Z[4] = (int64_t)X[12]*Y[0] + (int64_t)X[11]*Y[1] + (int64_t)X[10]*Y[2] + (int64_t)X[9]*Y[3] + (int64_t)X[0]*Y[4] + (int64_t)X[1]*Y[5] + (int64_t)X[2]*Y[6] + (int64_t)X[3]*Y[7] + (int64_t)X[4]*Y[8]; 
Z[5] = (int64_t)X[13]*Y[0] + (int64_t)X[12]*Y[1] + (int64_t)X[11]*Y[2] + (int64_t)X[10]*Y[3] + (int64_t)X[9]*Y[4] + (int64_t)X[0]*Y[5] + (int64_t)X[1]*Y[6] + (int64_t)X[2]*Y[7] + (int64_t)X[3]*Y[8]; 
Z[6] = (int64_t)X[14]*Y[0] + (int64_t)X[13]*Y[1] + (int64_t)X[12]*Y[2] + (int64_t)X[11]*Y[3] + (int64_t)X[10]*Y[4] + (int64_t)X[9]*Y[5] + (int64_t)X[0]*Y[6] + (int64_t)X[1]*Y[7] + (int64_t)X[2]*Y[8]; 
Z[7] = (int64_t)X[15]*Y[0] + (int64_t)X[14]*Y[1] + (int64_t)X[13]*Y[2] + (int64_t)X[12]*Y[3] + (int64_t)X[11]*Y[4] + (int64_t)X[10]*Y[5] + (int64_t)X[9]*Y[6] + (int64_t)X[0]*Y[7] + (int64_t)X[1]*Y[8]; 
Z[8] = (int64_t)X[16]*Y[0] + (int64_t)X[15]*Y[1] + (int64_t)X[14]*Y[2] + (int64_t)X[13]*Y[3] + (int64_t)X[12]*Y[4] + (int64_t)X[11]*Y[5] + (int64_t)X[10]*Y[6] + (int64_t)X[9]*Y[7] + (int64_t)X[0]*Y[8];} 

我計數時鐘週期如下

int32_t X[17], Y[9]; 
int64_t Z[9]; 
utype64 start, end; 
uint32_t i; 

srand(time(NULL)); 
for(i=0; i<17; i++) 
    X[i] = rand()%(uint32_t)pow(2.0, 29); 
srand(time(NULL)); 
for(i=0; i<9; i++) 
    Y[i] = rand()%(uint32_t)pow(2.0, 29); 

start=rdtsc(); 
end=rdtscp(); 
start=rdtsc(); 
for(i=0; i<10000000; i++) 
    schoolbook_9(X, Y, Z); 

end=rdtscp(); 
printf("\n%s%"PRIu64"\n", "The cycles count using SB of size 9 is :: ", (end-start)/10000000); 

我使用的rdtscp指令因爲我的系統支持它,可能它在32位機器上不可用,因此我測試了我的程序bo用/ out rdtscp。自變量X,Y和Z是X和Y爲32位,Z爲64位的數組。

所以,我的問題是如何獲得-O3的週期數?因爲對於當前的代碼我得到0循環。

flage -free-loop-vectorize設置爲-O3,如本頁所述https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html。這是否意味着循環已被矢量化?如果是,那麼如何確定矢量的長度(4個元素,6個元素等)?

+0

是的,我會在幾分鐘內更新問題。我打電話給rdtsc()和rdtscp()兩次,但實際上建議在G. Paoloni的白皮書中給他們打電話三次,網址是http://www.intel.com/content/dam/www/public/us/en /documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf – user110219

+1

'pow(2.0,29);' - >'1 << 29' –

回答

0

這是因爲end - start低於10000000-O3。您的部門生產0

utype64 result = end - start; 
utype64 cycle = 10000000; 
utype64 total = result/cycle; 
utype64 rest = result % cycle; 
printf("The cycles count using SB of size 9 is " PRIu64 
     " and the rest is " PRIu64 "\n", 
     total, rest); 

而且你不應該撥打兩次srand(time(NULL));。這是無用的,會產生奇怪的行爲。

注:我無法測試自己。

+0

是的,你是對的*(結束開始)* <10000000,這就是爲什麼我在-O3得到0。這就是我要問-O3應該怎麼做的原因?你不認爲邏輯*結束*總是大於*開始*?那麼,爲什麼utype64結果= *結束*> *開始*? *結束* - *開始*:*開始* - *結束*; ? – user110219

+0

@ user110219我不記得我爲什麼那樣做......我的壞。無論我不明白你的問題了。你有循環數,因爲它是0.我沒有看到問題。也許你可以使用['clock_gettime()'](https://linux.die.net/man/3/clock_gettime)。 – Stargateur

+0

@ user110219'-O [0 | 1 | 2 | 3]'應該沒有差別,所以行爲不應該改變。唯一改變的是你的程序更快。 – Stargateur