2016-11-23 86 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; 
} 
相关问题