2016-11-23 83 views
2

比方說,我有這樣的事情:如何爲某個類的某些成員強制執行16字節對齊?

class C 
{ 
private: 
    __m128i m0; 
    __m128i m1; 
    __m128i cm0; 

    int s0; 

... 

} 

這可能會導致問題,因爲M0,M1,和C 6-10都不能保證是對齊的16字節,允許對準相關的訪問衝突。如果我絕對想要有私人的simd級別會員,我可以保證我的聯盟,我應該怎麼做?

編輯:特別是在我的情況下,我正在使用具有__m128i成員的類的std :: vector(除了32位和64位整數。是否可以強制我的類成員的16字節對齊?一個std :: vector的內

+1

保證類成員的本地或靜態變量以及本地或靜態數組滿足對齊要求。如果您動態分配內存,則可能會遇到問題。我猜你正在嘗試使用'std :: vector '或類似的東西?如果是這樣,那麼說。 –

+0

你是對的,我正在嘗試使用像這樣的類的向量。任何建議? – MNagy

+1

如果沒有將整個班級對準到相同的值,則不能「排列成員」。否則,您可以通過班級允許的對齊來取代整個對象並打破成員對齊。 (這個類的佈局當然是固定的,並不是每個對象都決定的。) –

回答

1

這是一種解決方法,我發現解決我自己的問題

我所做的是雙重的:

起初,我一直在努力的東西,如:

std::vector<C> myVector(mySize); 

我選做,而不是:

C* myVector = _aligned_malloc(sizeof(C) * mySize, 16); 

其次,我添加了一些變量填充到C類,使得它的大小以字節爲單位將是16的倍數,我並不熱衷於浪費的空間需要,所以我可能會重寫未來的東西(可能是simd變量的一塊內存和其他塊的單獨塊)。

+0

讓編譯器爲你填充它。例如,你可以在代碼中看到'int size = sizeof(C)',然後查看asm輸出,[例如Godbolt上的](https://godbolt.org/g/p1RckS)。 (請注意,Godbolt的目標系統V ABI,而不是Windows ABI,並且它們可能並不總是同意結構佈局,但它們將始終填充所需對齊的倍數,以便數組中的所有元素都具有所需的對齊方式。) –

+0

但是,如果您不需要'std :: vector'的功能,則可以更容易地避免它,而不是傳遞分配對齊存儲的自定義分配器。 IDK爲什麼'std :: vector'在默認情況下不使用滿足對齊要求的分配器。 :( –

1

如果你不介意浪費一點RAM,你可以做一個aligned_holder包裝類,它將保證它所包含的對象將與你指定的任何對齊邊界對齊。 (請注意,浪費的RAM的量是等於指定對準邊界)

#include <stdio.h> 
#include <stddef.h> 
#include <stdint.h> 
#include <new> 

// Makes sure that its held object is always aligned to the specified alignment-value, 
// at the cost of using up some extra RAM. 
template<class T, int AlignTo=16> class aligned_holder 
{ 
public: 
    aligned_holder() 
    { 
     new (getAlignedPointer()) T(); 
    } 

    ~aligned_holder() 
    { 
     getAlignedObject().~T(); 
    } 

    T & getAlignedObject() {return *reinterpret_cast<T*>(getAlignedPointer());} 
    const T & getAlignedObjectConst() const {return *reinterpret_cast<const T*>(getAlignedPointerConst());} 

private: 
    char * getAlignedPointer() 
    { 
     const ptrdiff_t offset = intptr_t(_buf)%AlignTo; 
     return &_buf[(intptr_t)(AlignTo-offset)]; 
    } 

    const char * getAlignedPointerConst() const 
    { 
     const ptrdiff_t offset = intptr_t(_buf)%AlignTo; 
     return &_buf[(intptr_t)(AlignTo-offset)]; 
    } 

    char _buf[AlignTo+sizeof(T)]; 
}; 

...和單元測試,以(希望)驗證我沒有弄亂例如:

class IWannaBeAligned 
{ 
public: 
    IWannaBeAligned() 
    { 
     const intptr_t iThis = (intptr_t)(this); 
     if ((iThis % 16) != 0) printf("Error! object %p is not 16-byte aligned! (offset=%ld)\n", this, iThis%16); 
         else printf("Good, object %p is 16-byte aligned.\n", this); 
    } 

    ~IWannaBeAligned() 
    { 
     printf("Deleting object %p\n", this); 
    } 

    char buf[32]; // just to give it a more realistic object size than one byte 
}; 

int main() 
{ 
    { 
     printf("First, let's try it without the aligned_holder:\n"); 
     IWannaBeAligned notAligned; 
    } 

    printf("\n"); 

    { 
     printf("Now, we'll try it with the aligned_holder:\n"); 
     aligned_holder<IWannaBeAligned> isAligned; 
    } 

    return 0; 
} 
相關問題