最近和同事談到了ARM平臺下數(shù)據(jù)總線寬度及對齊方式對程序效率的影響問題,在定義結(jié)構(gòu)數(shù)據(jù)類型時,為了提高系統(tǒng)效率,要注意字長對齊原則。正好有點感觸和大家一起談?wù)劇?/p>
這里主要給大家解釋下所謂的對齊到底是什么?怎么對齊?為什么會對齊或者說對齊帶來什么樣的效率差異?
1.先看下面的例子:
#include
#pragma pack(4)
struct A
{
char a;
int b;
};
#pragma pack()
#pragma pack(1)
struct B
{
char a;
int b;
};
#pragma pack()
int main()
{
A a;
cout<
B b;
cout<
}
默認(rèn)的vc我記得是4字節(jié)對齊ADS下是一字節(jié)對齊,因為是c/c++社區(qū)大家對PC比較熟悉 我就談PC下的對齊。
PC下設(shè)計放的太長時間的有錯誤就別客氣直接說,大家可以看到在ms的vc下按4字節(jié)對齊和1字節(jié)對齊的結(jié)果是截然不同的分別為8和5為什么會有這樣的結(jié)果呢?這就是x86上字節(jié)對齊的作用。
為了加快程序執(zhí)行的速度,一些體系結(jié)構(gòu)以對齊的方式設(shè)計,通常以字長作為對齊邊界。對于一些結(jié)構(gòu)體變量,整個結(jié)構(gòu)要對齊在內(nèi)部成員變量最大的對齊邊界,如A,整個結(jié)構(gòu)以4為對齊邊界,所以sizeof(a)為8,而不是5。
如果是原始我們概念下的的A中的成員將會一個挨一個存儲,應(yīng)該只有char+int只有5個字節(jié)。這個差異就是由于對齊導(dǎo)致的。,然我們可以看到A的對齊要比B浪費3個字節(jié)的存儲空間。
那為什么還要采取對齊呢?
那是因為體系結(jié)構(gòu)的對齊和不對齊,是在時間和空間上的一個權(quán)衡。
字節(jié)對齊節(jié)省了時間。應(yīng)該是設(shè)計者考慮用空間換取時間。
為什么說對齊會提高效率呢節(jié)省時間?我想大家要理解的重點之重點就在這里了。
在我們常用的PC下總線寬度是32位
1.如果是總線寬度對齊的話
那么所有讀寫操作都是獲取一個<=32位數(shù)據(jù)可以一次保證在數(shù)據(jù)總線傳輸完畢
沒有任何的額外消耗
|1|2|3|4|5|6|7|8|
從1開始這里是a的起始位置,5起始為b的位置 訪問的時候
如果訪問a一次在總線傳輸8位其他24位無效的
訪問b時則一次在總線上傳輸32完成
讀寫均是一次完整
插敘一下 讀操作先要將讀地址放到地址總線上然后下個時鐘周期再從外部
存儲器接口上讀回數(shù)據(jù)通過數(shù)據(jù)總線返回需要兩個周期
而寫操作一次將地址及數(shù)據(jù)寫入相應(yīng)總線就完成了
讀操作要比寫操作慢一半
2.我們看訪問數(shù)據(jù)時如果不對齊地址的情況
|1|2|3|4|5|6|7|8|
此時a的地址沒變還在1而因為是不對齊則b的位置就在2處
這時訪問就帶來效率上問題 訪問a時沒問題還是讀會一個字節(jié)
但是2處地址因為不是總線寬度對齊一般的CPU在此地址操作將產(chǎn)生error
如sparc,MIPS。它們在硬件的設(shè)計上就強制性的要求對齊。在不對齊的地址上肯定發(fā)生錯誤
但是x86是支持非對齊訪問的
它通過多次訪問來拼接得到的結(jié)果,具體做法就是從1地址處先讀回后三字節(jié)234 暫存起來
然后再由5地址處讀回一個字節(jié)5 與234進(jìn)行拼接組成一個完整的int也就是b返回
大家看看如此的操作帶來的消耗多了不止三倍很明顯在字長對齊時效率要高許多
淡然這種效率僅僅是訪問多字節(jié)帶來的 如果還是進(jìn)行的byte操作那效率差不了多少
目前的開發(fā)普遍比較重視性能,所以對齊的問題,有2種不同的處理方法:
1) 有一種使用空間換時間做法是顯式的插入reserved成員:
struct A{
char a;
char reserved1[3]; //使用空間換時間
int b;
}a;
2) 隨便怎么寫,一切交給編譯器自動對齊。
還有一種將邏輯相關(guān)的數(shù)據(jù)放在一起定義
代碼中關(guān)于對齊的隱患,很多是隱式的。比如在強制類型轉(zhuǎn)換的時候。下面舉個例子:
unsigned int i = 0x12345678;
unsigned char *p=NULL;
unsigned short *p1=NULL;
p=&i;
*p=0x00;
p1=(unsigned short *)(p+1);
*p1=0x0000;
最后兩句代碼,從奇數(shù)邊界去訪問unsignedshort型變量,顯然不符合對齊的規(guī)定。
在x86上,類似的操作只會影響效率,但是在MIPS或者sparc上,可能就是一個error
-
ARM
+關(guān)注
關(guān)注
134文章
9097瀏覽量
367610 -
PC
+關(guān)注
關(guān)注
9文章
2082瀏覽量
154225 -
數(shù)據(jù)總線
+關(guān)注
關(guān)注
2文章
57瀏覽量
17571
原文標(biāo)題:嵌入式er日常!和同事交流ARM平臺字節(jié)對齊帶來的效率差異
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論