我如何为某个班级的某些成员执行16字节的一致性

How can I enforce 16-byte alignment for certain members of a class?

本文关键字:成员 执行 一致性 字节      更新时间:2023-10-16

假设我有类似的东西:

class C
{
private:
    __m128i m0;
    __m128i m1;
    __m128i cm0;
    int s0;
...
}

这可能会引起问题,因为M0,M1和CM0不能保证16个字节对齐,从而允许违反与对齐相关的访问。如果我绝对想拥有我可以保证的私人SIMD班级成员,我应该如何做?

编辑:特别是在我的情况下,我正在使用具有__m128i成员的班级的std ::向量(除了32和64位整数。是否可以强迫我的课堂成员的16字节对齐std :: vector?

这是我发现解决自己问题的解决方法。

我所做的是双重的:

最初,我一直在处理以下内容:

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

我选择做:

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

其次,我在C类中添加了一些可变填充,使其大小为16的倍数。我不热衷于浪费的空间,因此我可能会在将来重新工作(也许一个块SIMD变量的内存和其他块的单独块)。

如果您不介意浪费一点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 %pn", 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;
}

在C 11中,您可以使用Alignas。如该页面上的示例所示,您的代码可以像这样写:

class alignas(16) C
{
private:
    __m128i m0;
    __m128i m1;
    __m128i cm0;
    int s0;
...
}