ARM設計思想與高效C編程
一.RISC設計思想
本文引用地址:http://dyxdggzs.com/article/201610/307383.htmARM內核采用RISC體系結構。RISC是一種設計思想,其目標是設計出一套能在高時(shí)鐘頻率下單周期執行,簡(jiǎn)單而有效的指令集。RISC的設計重點(diǎn)在于由硬件執行的指令的復雜度,這是因為軟件比硬件容易提供更大的靈活性和更高的智能。因此,RISC設計對編譯器有更高的要求;相反,傳統的復雜指令集的計算機(CISC)則更側重于硬件執行指令的功能性,使CISC變得更復雜。
RISC設計思想主要由下面4個(gè)設計準則來(lái)實(shí)現:
·指令集
RISC處理器減少了指令種類(lèi),每條指令的長(cháng)度都是固定的,允許流水線(xiàn)在當前指令譯碼階段去取其下一條指令;而CISC處理器中,指令的長(cháng)度通常不固定,執行也需要多個(gè)周期。
·流水線(xiàn)
在理想情況下,流水線(xiàn)每周期前進(jìn)一步,可獲得最高的吞吐率;而CISC指令的執行需要調用微代碼的一個(gè)微程序。
·寄存器
RISC處理器擁有更多的通用寄存器,每個(gè)寄存器都可存放數據或地址。寄存器可為所有的數據操作提供快速的局部存儲訪(fǎng)問(wèn);而CISC處理器都是用于特定目的的專(zhuān)用 處理器。
·load-store結構
處理器只能處理寄存器中的數據。獨立的load和store指令用來(lái)完成數據在寄存器和外部存儲器之間的傳送。因為訪(fǎng)問(wèn)存儲器很耗時(shí),所以把存儲器訪(fǎng)問(wèn)和數據處理分開(kāi)。這樣有一個(gè)好處,那就是可反復地使用保存在寄存器中的數據,而避免多次訪(fǎng)問(wèn)存儲器。相反,在CISC結構中,處理器能夠直接處理存儲器中的數據。
二.ARM設計思想
為降低功耗,ARM處理器已被特殊設計成較小的核,較高的代碼密度。ARM內核不是一個(gè)純粹的RISC體系結構,這是為了使它能夠更好的適應其主要應用領(lǐng)域-嵌入式系統。在某種意義上,甚至可以認為ARM內核的成功,正是因為它沒(méi)有在RISC概念上沉入太深?,F在系統的關(guān)鍵并不在于單純的處理器速度,而在于有效的系統性能和功耗。
面向嵌入式系統的指令集
·一些特定指令的周期數可變
例如:多寄存器裝載/存儲的load/store指令的執行周期就是不確定的
·內嵌桶形移位器產(chǎn)生了更為復雜的指令
·Thumb 16位指令集
·條件執行
·增強指令
三.高效的C編程
1)C數據類(lèi)型的有效用法
·對于存放在寄存器中的局部變量,除了8位或16位的算數模運算符外,盡量不要使用char和short類(lèi)型。而要使用有符號或者無(wú)符號的int類(lèi)型。除法運算時(shí)使用無(wú)符號數執行速度更快。
·對于存放在主存儲器中的數組和全局變量,在滿(mǎn)足數據大小的前提下,應盡可能使用小尺寸的數據類(lèi)型,這樣做可以節省存儲空間。ARMv4體系結構可以有效的裝載和存儲所有寬度的數據,并可以使用遞增數組的指針來(lái)有效的訪(fǎng)問(wèn)數組。對于short類(lèi)型數組,要避免使用數組基地址的偏移,因為L(cháng)DRH指令不支持偏移尋址。
·由于隱式或者顯式的數據類(lèi)型轉換通常會(huì )有額外的指令周期開(kāi)銷(xiāo),所以在表達式中應盡量避免使用。load和store指令一般不會(huì )產(chǎn)生額外的轉換開(kāi)銷(xiāo),因為load和store指令是自動(dòng)完成數據類(lèi)型轉換的。
·對于函數參數和返回值應盡量避免使用char和short類(lèi)型。即使參數范圍比較小,也應該使用int類(lèi)型,以防止編譯器做不必要的類(lèi)型轉換。
2)高效的編寫(xiě)循環(huán)體
·使用減計數到零的循環(huán)結構,這樣編譯器就不需要分配一個(gè)寄存器來(lái)保存循環(huán)中止值,而且與0比較的指令也可以省略。
·使用無(wú)符號的循環(huán)計數值,循環(huán)繼續的條件為i!=0而不是i>0,這樣可以保證循環(huán)開(kāi)銷(xiāo)只有兩條指令。、
·如果事先知道循環(huán)體至少會(huì )執行一次,那么使用do-while循環(huán)要比f(wàn)or循環(huán)好,這樣可以使編譯器省去檢查循環(huán)計數值是否為0的步驟。
·展開(kāi)重要的循環(huán)體可降低循環(huán)開(kāi)銷(xiāo),但不要過(guò)度展開(kāi),如果循壞的開(kāi)銷(xiāo)對整個(gè)程序來(lái)說(shuō)占的比例很小,那么循環(huán)展開(kāi)反而會(huì )增加代碼量并降低cache性能。
·盡量使數組的大小是4或8的倍數,這樣就可以容易地以2,4,8次等多種選擇展開(kāi)循環(huán),而不需要擔心剩余數組元素的問(wèn)題。
3)高效的寄存器分配
·應該盡量限制函數內部循環(huán)所用局部變量的數目,最多不超過(guò)12個(gè),這樣,編譯器就可以把這些變量都分配給ARM寄存器。
·可以引導編譯器,通過(guò)查看是否屬于最內層循環(huán)變量來(lái)確定某個(gè)變量的重要性
4)高效的調用函數
·盡量限制函數參數不要超過(guò)4個(gè),這樣函數調用的效率會(huì )更高。也可以將幾個(gè)相關(guān)的參數組織在一個(gè)結構體中,用傳遞結構體指針來(lái)代替多個(gè)參數。
·把比較小的被調用函數和調用函數放在同一個(gè)原文件中,并且要先定義,后調用,編譯器就可以?xún)?yōu)化函數調用或者內聯(lián)較小的函數。
·對性能影響較大的重要函數可使用關(guān)鍵字_inline進(jìn)行內聯(lián)。
5)避免指針別名
·不要依賴(lài)編譯器來(lái)消除包含存儲訪(fǎng)問(wèn)的公共子表達式,而應建立一個(gè)新的局部變量來(lái)保存這個(gè)表達式的值,這樣可以保證只對這個(gè)表達式求職一次。
·避免使用局部變量的地址,否則對這個(gè)變量的訪(fǎng)問(wèn)效率會(huì )比較低。
6)高效的結構體安排
·結構體元素要按照元素的大小來(lái)排列,以最小的元素放在開(kāi)始,最大的元素安排在最后。
·避免使用很大的結構體,可以使用層次化的小結構體來(lái)代替。
·為了提高可移植性,人工對API的結構體添加填充位,這樣,結構體的安排將不會(huì )依賴(lài)于編譯器。
評論