動態內存申請對齊有什麼意義?

我在書上看見一個動態內存分配器的實現。這個分配器先申請一段內存,然後在把這段內存當作雙端棧通過變換棧頂指針來進行內存分配,實現代碼如下:

//對齊
#define ALIGNUP(naddress,nbytes) ((((uint)naddress)+
(nbytes)-1 ) (~((nbytes)-1)))
//初始化,申請一段空間,BYTEALIGN對齊
int init(size_t tsize,int BYTEALIGN)
{
_byte_alignment = BYTEALIGN;
tsize = ALIGNUP(tsize,_byte_alignment);
_all_allocated_memory = tsize + _byte_alignment;

_pmemory = (u8*)malloc(_all_allocated_memory);
if(!_pmemory)
{
return SYSTEM_MEMORY_SHORT;
}

_pbase = (u8*)ALIGNUP(_pmemory,_byte_alignment);
_pcap = (u8*)ALIGNUP(_pmemory+tsize,_byte_alignment);

_pframe_base = _pbase;
_pframe_cap = _pcap;

return SYSTEM_MEMORY_SUCCESS;
}
//分配
void* alloc(size_t tsize,bool tpos)
{
u8* _pret;

tsize = ALIGNUP(tsize,_byte_alignment);

if(_pframe_base+tsize&>_pframe_cap)
{

return NULL;
}

if(!tpos)
{
_pret = _pframe_base;
_pframe_base += tsize;
}
else
{
_pframe_cap -= tsize;
_pret = _pframe_cap;
}

return (void*)_pret;

}

這個BYTEALIGN應該取多少?(我只知道應該取2的冪,但是具體取多少有沒有什麼要求呢?)另外,這段代碼中使用ALIGNUP對齊有什麼意義?如果不對齊,應該也能工作吧。我只知道在實際內存中進行對齊是為了提高CPU讀取效率,但是這裡應該不存在CPU讀取的問題呀?


內存對齊絕非僅僅是效率問題,而是內存不對齊在某些情況下程序根本無法正常運行。

題主多用幾種不同 CPU 進行編程,會遇到內存不對齊就直接程序崩潰的情況的。

x86 只是一種內存可以隨意分配無需對齊的特例 CPU 而已。


1.

BYTEALIGN取決於CPU結構。x86和amd64等不同CPU上可能會有差別。

2.

&> 這裡應該不存在CPU讀取的問題呀

為什麼不存在呢?內存對齊就是為了提高CPU讀取效率。


既然是和內存管理相關的代碼,

估計對齊是為了能和分頁匹配。


好管理。

就像一個柜子,如果東西亂七八糟的堆在裡面,想把不用的扔掉,不好找不好扔;就算找出來扔了,它空出來的那個位置想放別的東西,又不見得就遇到一個剛好大小合適的;想整理一下吧,弄不好所有的東西都得倒騰一遍,真麻煩。

改進的辦法就是裝隔板,固定大小的隔板。一格不夠就兩格合併成一格用,即使東西只有1.5格大小,也佔2格。雖然看上去有點浪費,但是好管理。如果想整理一下,可以整格整格的挪,方便。

另:參見 什麼是位元組對齊,為什麼要對齊? - C++


個人理解了:

為了vectorization..充分利用CPU

參見

1. Data Alignment to Assist Vectorization

2. http://gcc.gnu.org/projects/tree-ssa/vectorization.html

設置正確的編譯器的情況下可以使得速度優化一倍

這種計算和並行還是有點不一樣的

引用一個例子:

foo () {
int i;

for (i=0; i&<256; i++){ a[i] = b[i] + c[i]; } }

這樣a, b, c被對齊了之後,可以成(大意)

foo () {
int i;

for (i=0; i&<256; i+=2){ a[i] = b[i] + c[i]; // a[i+1] = b[i+1] + c[i+1];//這兩部在CPU中會同時執行(即使是單核) } }

所以會快一倍

關於2的冪,這裡面的256應該不是隨便取的啦,和編譯器的優化有關,所以double的只能優化一倍。有個文獻,找不到了。。。


內存對齊為了:

1. 部分CPU不支持非對齊訪問

2. 大部分匯流排以BURST為單位讀內存,burst通常大於一個位元組,不對齊訪問會讓訪問速度變慢

3.cache讀入一般以cacheline為單位更新。不對齊會佔有多餘cacheline

一般來說,我們會用cacheline為單位對齊,這樣其他問題也得到相應權衡,linux內核還會提供這樣功能的宏。

但如果考慮到polution,對齊的技巧就更複雜了,有興趣可以進一步討論。


推薦閱讀:

在c++中,一個對象的內存分配問題?
電腦的主存儲器和主存、內存的關係是什麼?
為什麼沒有編程語言的內存管理是手動管理與自動垃圾回收相結合的?
linux怎麼管理空閑內存?
如何釋放Python佔用的內存?

TAG:C編程語言 | 內存管理 | C |