我們拿一個算法的代碼實現來舉例子,首先我們寫一個求階乘的子函數,這里我偷懶讓 ChatGPT 幫忙生成了一個:
// 階乘函數intfactorial_iterative(int n) { int result = 1; // 從1乘到n for (int i = 1; i <= n; ++i) { result *= i; } return result;}
// 示例int main() { int result_iterative = factorial_iterative(5); printf("5的階乘是: %dn", result_iterative);
return 0;}這種簡單的迭代算法的優(yōu)點是比較容易理解,一眼就可以看出程序員想干什么。
但這樣寫出來的程序缺點也很大,就是運行效率非常低,我們在算法編寫中最怕的就是for 循環(huán),因為這里面會存在大量的比較和跳轉,同時最容易產生一些代碼被無效的循環(huán)執(zhí)行。

這些缺點有的會被編譯器的優(yōu)化措施給規(guī)避掉,比如編譯器可以把一些需要內存訪問的變量先放到寄存器中,等計算完結果后,再把結果從寄存器中轉移到內存中,因為 CPU 讀取寄存器比讀取內存可快多了。
但是編譯器也不是萬能的,有些優(yōu)化他就做不到。比如,我們改成下面展開的樣子,超標量的流水線就開始起作用了。
// 階乘函數intfactorial_iterative(int n) { int result0 = 1, result1 = 1, result2 = 1,result3 = 1; // 從1乘到n for (int i = 1; i < n; i += 4) {
result0 *= i; result1 *= i + 1; result2 *= i + 2; result3 *= i + 3;
} return (result0 * result1 * result2 * result3);}首先,我們假設開啟了編譯器優(yōu)化,編譯器已經把所有內存訪問的變量在函數開始都歸置到了寄存器中,那么這時候我們可以看到,4 個 result 的乘法語句是相互獨立的,他們的計算過程不依賴于其他 3 個語句的計算結果。
這就好比安排了四個人,給他們算 4 個單獨的式子,假設他們計算能力相同,于是他們會在同一段時間后跑到黑板上來互相乘一下算個總的結果。
而如果我們只是簡單的做循環(huán)展開,不增加新的寄存器變量,也就是不加人的情況下是怎么樣的呢?
// 階乘函數intfactorial_iterative(int n) { int result = 1; // 從1乘到n for (int i = 1; i < n; i += 4) {
result *= i; result *= i + 1; result *= i + 2; result *= i + 3;
} return (result * result * result * result);}這里只放了一個聰明的孩子做算式,不過你看他要做的 4 個算式,其中后一個算式總要用到前一個算式的結果,他即便再聰明也得一個一個的算。
這就是超標量流水線的用處,當然展開多少還需要我們自己衡量,本質上也是用空間換時間,另外寄存器可是稀缺資源。
-
處理器
+關注
關注
68文章
20346瀏覽量
255397 -
mcu
+關注
關注
147文章
19176瀏覽量
404944 -
代碼
+關注
關注
30文章
4979瀏覽量
74446 -
編譯器
+關注
關注
1文章
1673瀏覽量
52003
發(fā)布評論請先 登錄
什么是超標量處理器的流水線?超標量處理器的特點有哪些?
FPGA中的流水線設計
現代RISC中的流水線技術
什么是超標量技術/FADD?
流水線中的相關培訓教程[4]
FPGA之流水線練習(3):設計思路
如何選擇合適的LED生產流水線輸送方式
嵌入式_流水線
什么是流水線 Jenkins的流水線詳解
首款Cortex-M7內核超高性能MCU性能揭秘
H7的特點 什么是超標量流水線
GD32H7如何利用超標量流水線
評論