国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

查看: 2050|回復(fù): 0
打印 上一主題 下一主題

有這10個(gè)關(guān)鍵點(diǎn),在ARM下高效C編程沒(méi)問(wèn)題!

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2018-4-28 09:47:46 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
關(guān)鍵詞: 嵌入式、arm、C語(yǔ)言
通過(guò)一定的方法來(lái)編寫(xiě)C程序,可以幫助C編譯器生成執(zhí)行速度更快的ARM代碼。下面就是一些與性能相關(guān)的關(guān)鍵點(diǎn):

1.對(duì)局部變量、函數(shù)參數(shù)和返回值要使用signed和unsigned int類(lèi)型。這樣可以避免類(lèi)型轉(zhuǎn)換,而且可高效地使用ARM的32位數(shù)據(jù)操作指令。

2.最高效的循環(huán)體形式是減計(jì)數(shù)到零(counts down to zero)的do-while循環(huán)。

3.展開(kāi)重要的循環(huán)來(lái)減少循環(huán)的開(kāi)銷(xiāo)。

4.不要依賴(lài)編譯器來(lái)優(yōu)化掉重復(fù)的存儲(chǔ)器訪問(wèn)。指針別名會(huì)阻止編譯器的這種優(yōu)化。

5.盡可能把函數(shù)參數(shù)的個(gè)數(shù)限制在4個(gè)以內(nèi)。如果函數(shù)參數(shù)都存放在寄存器內(nèi),那么函數(shù)調(diào)用就會(huì)快得多。

6.按元素尺寸從小到大排列的方法來(lái)安排結(jié)構(gòu)體,特別是在thumb模式下編譯。

7.不要使用位域,可以用掩碼和邏輯操作來(lái)替代。

8.避免除法,可以用倒數(shù)的乘法來(lái)替代。

9.避免邊界不對(duì)齊的數(shù)據(jù)。如果數(shù)據(jù)有可能邊界不對(duì)齊,那么就要使用char *指針類(lèi)型來(lái)訪問(wèn)。

10.在C編譯器中使用內(nèi)嵌匯編可以利用到C編譯器本來(lái)不支持的指令或優(yōu)化。

一、 數(shù)據(jù)類(lèi)型使用上的優(yōu)化

1.局部變量
一個(gè)char類(lèi)型的數(shù)據(jù)比int類(lèi)型的數(shù)據(jù)占用更小的寄存器空間或者更小的ARM堆棧空間。這兩種設(shè)想對(duì)于ARM來(lái)說(shuō),都是錯(cuò)誤的。所有的ARM寄存器都是32位的,所有的堆棧入口至少是32位的。當(dāng)我們執(zhí)行i++,要利用當(dāng)i=255后,i++=0這個(gè)條件時(shí),可以把它定義為char類(lèi)型。

2.函數(shù)參數(shù)
盡管寬和窄的函數(shù)調(diào)用規(guī)則各有其優(yōu)點(diǎn),但char或short類(lèi)型的函數(shù)參數(shù)和返回值都會(huì)產(chǎn)生額外的開(kāi)銷(xiāo),導(dǎo)致性能的下降,并增加了代碼尺寸。所以,即使是傳輸一個(gè)8位的數(shù)據(jù),函數(shù)參數(shù)和返回值使用int類(lèi)型也會(huì)更有效。     

總結(jié):

1)對(duì)于存放在寄存器中的局部變量,除了8位或16位的算術(shù)模運(yùn)算外,盡量不要使用char和short類(lèi)型,而要使用有符號(hào)或無(wú)符號(hào)int類(lèi)型。除法運(yùn)算時(shí)使用無(wú)符號(hào)數(shù)執(zhí)行速度更快。

2)對(duì)于存放在主存儲(chǔ)器中的數(shù)組和全局變量,在滿足數(shù)據(jù)大小的前提下,應(yīng)盡可能使用小尺寸的數(shù)據(jù)類(lèi)型,這樣可以節(jié)省存儲(chǔ)空間。ARMv4體系結(jié)構(gòu)可以有效地裝載和存儲(chǔ)所有寬度的數(shù)據(jù),并可以使用遞增數(shù)組指針來(lái)有效地訪問(wèn)數(shù)組。對(duì)于short類(lèi)型數(shù)組,要避免使用數(shù)組基地址的偏移量,因?yàn)長(zhǎng)DRH指令不支持偏移尋址。

3)通過(guò)讀取數(shù)組或全局變量并賦給不同類(lèi)型的局部變量時(shí),或者把局部變量寫(xiě)入不同類(lèi)型的數(shù)組或者全局變量時(shí),要進(jìn)行顯式數(shù)據(jù)類(lèi)型轉(zhuǎn)換。這種轉(zhuǎn)換使編譯器可以明確、快速地處理,把存儲(chǔ)器中數(shù)據(jù)寬度比較窄的數(shù)據(jù)類(lèi)型擴(kuò)展,并賦給寄存器中較寬的類(lèi)型。

4)由于隱式或者顯式的數(shù)據(jù)類(lèi)型轉(zhuǎn)換通常會(huì)有額外的指令周期開(kāi)銷(xiāo),所以在表達(dá)式中應(yīng)盡量避免使用。Load和store指令一般不會(huì)產(chǎn)生額外的轉(zhuǎn)換開(kāi)銷(xiāo),因?yàn)閘oad和store指令是自動(dòng)完成數(shù)據(jù)類(lèi)型轉(zhuǎn)換的。

5)對(duì)于函數(shù)參數(shù)和返回值應(yīng)盡量避免使用char和short類(lèi)型。即使參數(shù)范圍比較小,也應(yīng)該使用int類(lèi)型,以防止編譯器做不必要的類(lèi)型轉(zhuǎn)換。

二、C循環(huán)結(jié)構(gòu)

在ARM上,一個(gè)循環(huán)其實(shí)只要2條指令就足夠了:

一條減法指令,進(jìn)行循環(huán)減法計(jì)數(shù),同時(shí)設(shè)置結(jié)果的條件標(biāo)志;
一條條件分支指令。

這里的關(guān)鍵是,循環(huán)的終止條件應(yīng)為減計(jì)數(shù)到零,而不是計(jì)數(shù)增加到某個(gè)特定的限制值。由于減計(jì)數(shù)結(jié)構(gòu)已存儲(chǔ)在條件標(biāo)志里,與零比較的指令就可以省略了。由于不用i作為數(shù)組的下標(biāo)索引,采用減計(jì)數(shù)就沒(méi)有任何問(wèn)題了。

總而言之,無(wú)論對(duì)于有符號(hào)的循環(huán)計(jì)數(shù)值,都應(yīng)使用i!=0作為循環(huán)的結(jié)束條件。對(duì)有符號(hào)數(shù)i,這比使用條件i>0少了一條指令。

總結(jié):
1) 使用減計(jì)數(shù)到零的循環(huán)結(jié)構(gòu),這樣編譯器就不需要分配一個(gè)寄存器來(lái)保存循環(huán)終止值,而且與0比較的指令也可以省略。

2) 使用無(wú)符號(hào)的循環(huán)計(jì)數(shù)值,循環(huán)繼續(xù)的條件為i!=0而不是i>0,這樣可以保證循環(huán)開(kāi)銷(xiāo)只有兩條指令。

3) 如果事先知道循環(huán)體至少會(huì)執(zhí)行一次,那么使用do-while循環(huán)要比f(wàn)or循環(huán)要好,這樣可以使編譯器省去檢查循環(huán)計(jì)數(shù)值是否為零的步驟。

4) 展開(kāi)重要的循環(huán)體可降低循環(huán)開(kāi)銷(xiāo),但不要過(guò)度展開(kāi),如果循環(huán)的開(kāi)銷(xiāo)對(duì)整個(gè)程序來(lái)說(shuō)占的比例很小,那么循環(huán)展開(kāi)反而會(huì)增加代碼量并降低cache的性能。

5) 盡量使數(shù)組的大小是4或8的倍數(shù),這樣可以容易的以2,4,8次等多種選擇展開(kāi)循環(huán),而不需要擔(dān)心剩余數(shù)組元素的問(wèn)題。

三、寄存器分配

高效的寄存器分配:應(yīng)該盡量限制函數(shù)內(nèi)部循環(huán)所用局部變量的數(shù)目,最多不超過(guò)12個(gè),這樣,編譯器就可以把這些變量都分配給ARM寄存器。

四、函數(shù)調(diào)用

4寄存器規(guī)則:帶有4個(gè)或者更少參數(shù)的函數(shù),要比多于4個(gè)參數(shù)的函數(shù)執(zhí)行效率高得多。對(duì)帶有少于4個(gè)參數(shù)的函數(shù)來(lái)說(shuō),編譯器可以用寄存器傳遞所有的參數(shù);而對(duì)于多于4個(gè)參數(shù)的函數(shù),函數(shù)調(diào)用者和被調(diào)用者必須通過(guò)訪問(wèn)堆棧來(lái)傳遞一些參數(shù)。

如果函數(shù)體積很小,只用到很少的寄存器,那么還有一些其他的方法來(lái)減少函數(shù)調(diào)用的開(kāi)銷(xiāo)。可以把調(diào)用函數(shù)和被調(diào)用函數(shù)放在同一個(gè)C文件中,這樣編譯器就知道了被調(diào)用函數(shù)生成的代碼,并以此對(duì)調(diào)用函數(shù)進(jìn)行一些優(yōu)化。

總結(jié):
1) 盡量限制函數(shù)的參數(shù),不要超過(guò)4個(gè),這樣函數(shù)調(diào)用的效率會(huì)更高。也可以將幾個(gè)相關(guān)的參數(shù)組織在一個(gè)結(jié)構(gòu)體中,用傳遞結(jié)構(gòu)體指針來(lái)代替多個(gè)參數(shù)。
2) 把比較小的被調(diào)用函數(shù)和調(diào)用函數(shù)放在同一個(gè)源文件中,并且要先定義,后調(diào)用,編譯器就可以優(yōu)化函數(shù)調(diào)用或者內(nèi)聯(lián)較小的函數(shù)。
3) 對(duì)性能影響較大的重要函數(shù)可使用關(guān)鍵字_inline進(jìn)行內(nèi)聯(lián)。

五、指針別名

定義:當(dāng)2個(gè)指針指向同一個(gè)地址對(duì)象時(shí),這2個(gè)指針被稱(chēng)作該對(duì)象的別名(alias)。如果對(duì)其中一個(gè)指針進(jìn)行寫(xiě)入,就會(huì)影響從另一個(gè)指針的讀出。在一個(gè)函數(shù)中,編譯器通常不知道哪一個(gè)指針是別名,哪一個(gè)不是;或哪一個(gè)指針有別名,哪一個(gè)沒(méi)有。

避免指針別名:
1) 不要依賴(lài)編譯器來(lái)消除包含存儲(chǔ)器訪問(wèn)的公共子表達(dá)式,而應(yīng)建立一個(gè)新的局部變量來(lái)保存這個(gè)表達(dá)式的值,這樣可以保證只對(duì)這個(gè)表達(dá)式求一次值;
2) 避免使用局部變量的地址,否則對(duì)這個(gè)變量的訪問(wèn)效率會(huì)比較低。

六、結(jié)構(gòu)體安排

在ARM上使用結(jié)構(gòu)體有2個(gè)問(wèn)題需要考慮:結(jié)構(gòu)體地址邊界對(duì)齊和結(jié)構(gòu)體總的大小。

獲得高效結(jié)構(gòu)體的原則:
1) 把所有8位大小的元素安排在結(jié)構(gòu)體的前面;
2) 以此安排16位、32位和64位的元素;
3) 把所有數(shù)組和比較大的元素安排在結(jié)構(gòu)體最后;
4) 對(duì)于一條指令,如果結(jié)構(gòu)體太大而不能訪問(wèn)所有的元素,那么把元素組織到一個(gè)子結(jié)構(gòu)體中。編譯器可以維持單獨(dú)的子結(jié)構(gòu)體的指針。

總結(jié):
結(jié)構(gòu)體元素要按照元素的大小來(lái)排列,以最小的元素放在開(kāi)始,最大的元素安排在最后;避免使用很大的結(jié)構(gòu)體,可以用層次化的小結(jié)構(gòu)體來(lái)代替;為了提高可移植性,人工對(duì)API的結(jié)構(gòu)體增加填充位,這樣,結(jié)構(gòu)體的安排將不會(huì)依賴(lài)與編譯器;在API的結(jié)構(gòu)體中要謹(jǐn)慎使用枚舉類(lèi)型。一個(gè)枚舉類(lèi)型的大小是編譯器相關(guān)的。

七、位域

注意事項(xiàng):
1) 應(yīng)避免使用位域,而使用#define或者enum來(lái)定義屏蔽位;
2) 使用整型邏輯運(yùn)算AND、OR、“異或”操作和屏蔽對(duì)位域進(jìn)行測(cè)試、取反和設(shè)置操作。這些操作編譯效率高,還可以同時(shí)對(duì)多個(gè)位域進(jìn)行測(cè)試、取反和設(shè)置。

八、邊界不對(duì)齊數(shù)據(jù)和字節(jié)排列方式(大/小端)

邊界不對(duì)齊數(shù)據(jù)和字節(jié)排列方式這2個(gè)問(wèn)題,可使內(nèi)存訪問(wèn)和移植問(wèn)題復(fù)雜化。須考慮數(shù)組指針是否邊界對(duì)齊,ARM配置是大端(big-endian),還是小端(little-endian)的存儲(chǔ)器系統(tǒng)。

總結(jié):
1) 盡量避免使用邊界不對(duì)齊的數(shù)據(jù);
2) 使用類(lèi)型char *可指向任意字節(jié)邊界的數(shù)據(jù)。通過(guò)讀字節(jié)來(lái)訪問(wèn)數(shù)據(jù),使用邏輯操作來(lái)組合數(shù)據(jù),這樣代碼就不會(huì)依賴(lài)于邊界是否對(duì)齊或者ARM的字節(jié)排列方式的配置;
3) 為了快速訪問(wèn)邊界不對(duì)齊的結(jié)構(gòu)體,可以根據(jù)指針邊界和處理器的字節(jié)排序方式寫(xiě)出不同的程序變體。

九、除法

ARM硬件上不支持除法指令,當(dāng)代碼中出現(xiàn)除法運(yùn)算時(shí),ARM編譯器會(huì)調(diào)用C庫(kù)函數(shù)(有符號(hào)的除法調(diào)用_rt_sdiv,無(wú)符號(hào)的調(diào)用_rt_udiv),來(lái)實(shí)現(xiàn)除法操作。有許多不同類(lèi)型的除法程序來(lái)適應(yīng)不同的除數(shù)和被除數(shù)。

總結(jié):
1) 盡可能避免使用除法。對(duì)環(huán)形緩沖區(qū)的處理可以不用除法。

2) 如果不能避免除法運(yùn)算,那么盡可能考慮使用除法程序同時(shí)產(chǎn)生商n/d和余數(shù)n%d的好處。

3) 對(duì)于重復(fù)對(duì)同一除數(shù)d的除法,預(yù)先計(jì)算好s=(2k-1)/d。可用乘以s的2k位乘法來(lái)代替除以d的k位無(wú)符號(hào)整數(shù)除法。

4)使用2的整數(shù)次冪作除數(shù)。當(dāng)2的整數(shù)次冪做除數(shù)時(shí),編譯器會(huì)自動(dòng)將除法運(yùn)算轉(zhuǎn)換成移位運(yùn)算。所以在編寫(xiě)程序算法時(shí),盡量使用2的整數(shù)次冪做除數(shù)。

5)求余運(yùn)算。可以將一些典型的求余運(yùn)算進(jìn)行轉(zhuǎn)換,以避免在程序中使用除法運(yùn)算。

如:
uint counter1(uint count)
{
        return (++count%60);
}
轉(zhuǎn)換成:
uint counter2(uint count)
{
        if (++count >=60)
        count=0;
        return (count);
}

大多數(shù)ARM處理器硬件上并不支持浮點(diǎn)運(yùn)算。這樣在一個(gè)對(duì)價(jià)格敏感的嵌入式應(yīng)用系統(tǒng)中,可節(jié)省空間和降低功耗。除了硬件向量浮點(diǎn)累加器VFP和ARM7500FE上的浮點(diǎn)累加器FPA外,C編譯器必須在軟件上提供浮點(diǎn)支持。

十、內(nèi)聯(lián)函數(shù)和內(nèi)嵌匯編

高效地調(diào)用函數(shù),使用內(nèi)聯(lián)函數(shù)可以完全去除函數(shù)調(diào)用的開(kāi)銷(xiāo),另外許多編譯器允許在C源程序中使用內(nèi)嵌匯編。使用包含匯編的內(nèi)嵌函數(shù),可以使編譯器支持通常不能有效使用的ARM指令和優(yōu)化方法。

內(nèi)聯(lián)函數(shù)和內(nèi)嵌匯編最大的好處是,可以實(shí)現(xiàn)一些在C語(yǔ)言部分中通常難以完成的操作。使用內(nèi)聯(lián)函數(shù)要比使用#define宏定義更好,因?yàn)楹笳卟粰z查函數(shù)參數(shù)和返回值的類(lèi)型。

以下課程可免費(fèi)試聽(tīng)C語(yǔ)言、電子PCBSTM32LinuxFPGA、JAVA、安卓等。
想學(xué)習(xí)的你和我聯(lián)系預(yù)約就可以免費(fèi)聽(tīng)課了。
宋工企鵝號(hào):35--24-65--90-88   Tel/WX:173--17--95--19--08

本版積分規(guī)則

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號(hào) | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 一级做a爰片性色毛片视频图片 | 五月天婷婷视频在线观看 | 老色批午夜免费视频网站 | 四虎国产精品永久免费网址 | 久久8 | 五月综合色婷婷影院在线观看 | 97精品国产自在现线免费观看 | 黄色a视频在线观看 | 成人精品视频一区二区三区尤物 | 亚洲欧洲精品成人久久曰影片 | 欧美激情精品久久久久久久 | 国产日韩精品在线 | 日本h肉动漫在线观看免费 日本a中文字幕 | 天天操天天摸天天干 | 日本高清中文字幕视频在线 | 免费污污视频网站 | 亚洲精品中文字幕乱码影院 | 欧美 亚洲 一区 | 99在线精品视频在线观看 | 韩国福利一区二区美女视频 | 亚洲视频综合 | 天堂网视频在线观看 | 成人精品国产亚洲欧洲 | 国产精品欧美久久久久天天影视 | 免费看啪啪的网站 | 国内精品久久久久影院一蜜桃 | 五月婷婷激情综合网 | 一卡二卡四卡无人区免费 | 国产视频自拍一区 | 亚洲三级黄 | 日本一区二区三区精品视频 | 痴女中文字幕在线视频 | 日韩国产欧美在线观看 | 毛片在线网 | 三级 在线播放 | 在线观看一区二区精品视频 | 精品国产一区二区三区不卡蜜臂 | 久草成人在线视频 | 一级特级女人18毛片免费视频 | 成人精品一区二区三区中文字幕 | 国产91免费在线观看 |