搞汽車嵌入式開發(fā)的小伙伴,似乎對編程語言要求不高。只要能用,程序能動,咱們就縫縫補補又三年。雖然是這么說,但是,作為一名開發(fā)者,咱們還是要有上進心的。畢竟汽車級MCU資源不是那么豐富,能在代碼上做一些優(yōu)化,提升產(chǎn)品性能,也算咱們的feature。本文,聊一聊提升程序效率的一種方式:減少for循環(huán),提升執(zhí)行效率。問題描述:對地址范圍0x200000~0x2FFFFF的數(shù)據(jù)進行加密計算,每次只能輸入16 Byte字節(jié)(一個Block)進行計算,上一次的計算結果參與下一次計算。熟悉CMAC加密的同學應該看出來,這就是一個典型的CMAC計算。常規(guī)編碼,我們會怎么寫呢?示意如下:for (; CmacData.leftDataLen > 16; ) { AesCmac_Cal128BitLen(addressIn); addressIn += 16U; CmacData.leftDataLen -= 16U; }
while (CmacData.leftDataLen > 16) { AesCmac_Cal128BitLen(addressIn); addressIn += 16U; CmacData.leftDataLen -= 16U; } 初始長度CmacData.leftDataLen = 0x100000,也就是1 MBytes。那么,這樣的寫法會消耗多少時間呢?本文用Timer(定時器)統(tǒng)計,用時統(tǒng)計,示意如下:TimeArr[0] = OsTimer0_GetTicks(); for (; CmacData.leftDataLen > 16; ) { AesCmac_Cal128BitLen(addressIn); addressIn += 16U; CmacData.leftDataLen -= 16U; } TimeArr[1] = OsTimer0_GetTicks() - TimeArr[0]; for寫法平均用時8567044Ticks,while寫法平均用時8569820Ticks。其中,Timer主頻60MHz,換算下來,兩者分別用時:142.784ms、142.830ms。能否優(yōu)化上述的寫法呢?答:可以。優(yōu)化思路:如上的循環(huán)中,每16 Bytes進行一次判斷,而且每次運算,均需要進行address的累加和長度的遞減。所以,如果把字節(jié)提高到64 Bytes執(zhí)行一次判斷,可以減少3次address的累加和長度的遞減,即:適當增加判斷的顆粒度。
while (CmacData.leftDataLen > 64) { AesCmac_Cal128BitLen(addressIn); AesCmac_Cal128BitLen(addressIn+16); AesCmac_Cal128BitLen(addressIn+32); AesCmac_Cal128BitLen(addressIn+48); addressIn += 64U; CmacData.leftDataLen -= 64U; }
用時:7586131Ticks,即:126.436ms。 修改for代碼如下所示: for (;CmacData.leftDataLen > 64;) { AesCmac_Cal128BitLen(addressIn); AesCmac_Cal128BitLen(addressIn+16); AesCmac_Cal128BitLen(addressIn+32); AesCmac_Cal128BitLen(addressIn+48); addressIn += 64U; CmacData.leftDataLen -= 64U; }
用時:7585583Ticks,即:126.426ms。 統(tǒng)計對比如下:

所以,遇到for循環(huán)時,可以適當放大判斷的顆粒度。
|