內(nèi)存對(duì)齊

ncnn中內(nèi)存對(duì)齊

在ncnn源碼net.cpp中,int Net::load_param(const unsigned char* _mem)函數(shù)中你可以看到這么一段代碼:

    if ((unsigned long)_mem & 0x3)
    {
        // reject unaligned memory
        fprintf(stderr, "memory not 32-bit aligned at %p\n", _mem);
        return -1;
    }

將指針地址和0x3進(jìn)行位與,目的其實(shí)是判斷指針地址是不是4字節(jié)對(duì)齊的,主要的原因是不對(duì)齊,cpu讀取的效率會(huì)變低,具體舉例就是本來只需要一次讀取的可能需要兩次讀取了。

什么是內(nèi)存對(duì)齊

cpu在讀取內(nèi)存時(shí)是一塊一塊進(jìn)行讀取的,塊的大小可以是2,4,8,16(總之是2的倍數(shù))。舉例來說:如果一個(gè)變量int 的起始地址偏移是1,那么CPU要取這個(gè)地址上的數(shù)據(jù),需要取兩次。如圖,cpu按四字節(jié)讀取,第一次讀取0x0 ~ 0x3,


image.png

cpu第二次讀取0x4 ~ 0x7,這時(shí)cpu才能讀到這個(gè)int的值。


image.png

如果內(nèi)存對(duì)齊了呢,就如下只需一次讀?。?br>
image.png
typedef struct {
    int a;             //4字節(jié)
    double b;      //8字節(jié)
    short c;         //2字節(jié)
}A;

typedef struct {
    int a;             //4字節(jié)
    short b;         //2字節(jié)
    double c;      //8字節(jié)
}B;

上面兩個(gè)結(jié)構(gòu)體,理論上來說它們是一樣大小的,但是當(dāng)我們sizeof(A)=24,sizeof(B)=16。分析一下:對(duì)結(jié)構(gòu)體A來說,a占4個(gè)字節(jié),占從0 ~ 3的字節(jié),b是double類型占8個(gè)字節(jié),占從8 ~ 15的字節(jié),c占兩個(gè)字節(jié),從16 ~ 17的字節(jié)。 對(duì)結(jié)構(gòu)體B來說,a占4個(gè)字節(jié),從0 ~ 3,b占兩個(gè)字節(jié)從4 ~ 6;c占8個(gè)字節(jié)從8 ~ 15。當(dāng)然上面的分析是針對(duì)gcc編譯器的,不同的編譯器有不同的對(duì)齊規(guī)則。

內(nèi)存對(duì)齊規(guī)則

1、 對(duì)于結(jié)構(gòu)的各個(gè)成員,第一個(gè)成員位于偏移為0的位置,以后每個(gè)數(shù)據(jù)成員的偏移量必須是min(#pragma pack()指定的數(shù),這個(gè)數(shù)據(jù)成員的自身長(zhǎng)度) 的倍數(shù)。
2、 在數(shù)據(jù)成員完成各自對(duì)齊之后,結(jié)構(gòu)(或聯(lián)合)本身也要進(jìn)行對(duì)齊,對(duì)齊將按照#pragma pack指定的數(shù)值和結(jié)構(gòu)(或聯(lián)合)最大數(shù)據(jù)成員長(zhǎng)度中,比較小的那個(gè)進(jìn)行。
3、 必須是2的整數(shù)倍

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容