每當有人問「什麼時候才要學資料結構?」
就會說「當你發現記憶體能用就會去學。」
「那為什麼要使用移位?有乘法就可以了!」
「當你發現執行速度不夠快,就要學去用了。」
我們先來看乘法的程式需要多少時間
int shift = 1;
int main() {
LARGE_INTEGER t1, t2, ts;
QueryPerformanceFrequency(&ts);
QueryPerformanceCounter(&t1);
printf("%d\n", shift);
shift = shift*32;
printf("%d\n", shift);
QueryPerformanceCounter(&t2);
printf("執行時間: %lf\n",(t2.QuadPart-t1.QuadPart)/(double)(ts.QuadPart));
return 0;
}
使用乘法,自乘32,則需要0.000346秒
接下來,再看移位的程式需要多少時間
int shift = 1;
int main() {
LARGE_INTEGER t1, t2, ts;
QueryPerformanceFrequency(&ts);
QueryPerformanceCounter(&t1);
printf("%d\n", shift);
shift = shift<<5;
printf("%d\n", shift);
QueryPerformanceCounter(&t2);
printf("執行時間: %lf\n",(t2.QuadPart-t1.QuadPart)/(double)(ts.QuadPart));
return 0;
}
利用移位,左移5次代表自乘32,則需要0.000290秒
左移5次比自乘32,快0.000056秒 (0.056毫秒)
====================分格線====================
因為乘法需要用數十個指令周期(大概是70個左右)來完成;而移位則只需要3-5個指令周期,因此移位動作比乘法動作更有效率。
此外,我們推論兩者時間差距會隨乘數而愈來愈大
我們來看看左移10次
int shift = 1;
int main() {
LARGE_INTEGER t1, t2, ts;
QueryPerformanceFrequency(&ts);
QueryPerformanceCounter(&t1);
printf("%d\n", shift);
shift = shift<<10;
printf("%d\n", shift);
QueryPerformanceCounter(&t2);
printf("左移10次執行時間: %lf\n",(t2.QuadPart-t1.QuadPart)/(double)(ts.QuadPart));
return 0;
}
再看看乘1024的時間結果
int shift = 1;
int main() {
LARGE_INTEGER t1, t2, ts;
QueryPerformanceFrequency(&ts);
QueryPerformanceCounter(&t1);
printf("%d\n", shift);
shift = shift*1024;
printf("%d\n", shift);
QueryPerformanceCounter(&t2);
printf("乘1024執行時間: %lf\n",(t2.QuadPart-t1.QuadPart)/(double)(ts.QuadPart));
return 0;
}
自乘1024,需要0.000402秒
左移10次,需要0.000328秒
乘1024,兩者相差0.000074秒 (0.074毫秒)
乘32,兩者相差0.000056秒 (0.056毫秒)
====================分格線====================
可能大家會問:就為了那0.0幾毫秒,那為什麼還需要設計移位,而且CPU也可以做到乘法,這不就造成更多成本?
其實並不一定,上述所提供的以C語言再轉換成組語,再運作。
但我們並不了解組譯器有沒有為大家作優化,把乘法的部分,轉成移位方式。
因此所產生的幾毫秒差異,可能是電腦所產生的差異。
但我們從計算機結構中可以得知,乘法的確是比移位有效。
希望明天可以整理完資料...