C++ 如何对类的某些成员强制执行16字节对齐?

C++ 如何对类的某些成员强制执行16字节对齐?,c++,sse,simd,memory-alignment,class-members,C++,Sse,Simd,Memory Alignment,Class Members,比如说,我有一些类似于: class C { private: __m128i m0; __m128i m1; __m128i cm0; int s0; ... } std::vector<C> myVector(mySize); 这可能会导致问题,因为m0、m1和cm0不能保证16字节对齐,从而导致与对齐相关的访问冲突。如果我真的想拥有私有simd类成员,我可以保证他们的一致性,我应该怎么做 编辑:特别是在我的例子中,我使用的是一个类的st

比如说,我有一些类似于:

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

    int s0;

...

}
std::vector<C> myVector(mySize);
这可能会导致问题,因为m0、m1和cm0不能保证16字节对齐,从而导致与对齐相关的访问冲突。如果我真的想拥有私有simd类成员,我可以保证他们的一致性,我应该怎么做


编辑:特别是在我的例子中,我使用的是一个类的std::vector,该类有uu m128i成员(除了32位和64位整数之外)。是否可以在std::vector中强制对我的类成员进行16字节对齐?

这是一个解决我自己问题的解决方法

我做了两件事:

起初,我一直在做这样的工作:

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

    int s0;

...

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

其次,我在C类中添加了一些变量填充,这样它的字节大小将是16的倍数。我不喜欢浪费空间,所以我可能会在将来返工(可能一块内存用于simd变量,另一块内存用于其他变量).

如果您不介意浪费一点RAM,可以使用aligned_holder包装类来保证它所持有的对象将与您指定的对齐边界对齐。(请注意,浪费的RAM量等于指定的对齐边界)

#包括
#包括
#包括
#包括
//确保其保持的对象始终与指定的对齐值对齐,
//以消耗掉一些额外的内存为代价。
模板类对齐固定器
{
公众:
对齐的固定器()
{
新的(getAlignedPointer())T();
}
~u holder()
{
getAlignedObject().~T();
}
T&getAlignedObject(){return*重新解释强制转换(getAlignedPointer());}
常量T&getAlignedObjectConst()常量{return*重新解释_cast(getAlignedPointerConst());}
私人:
char*getAlignedPointer()
{
常量ptrdiff\u t offset=intptr\u t(\u buf)%AlignTo;
返回值和基本值[(输入)(对齐到偏移)];
}
常量字符*getAlignedPointerConst()常量
{
常量ptrdiff\u t offset=intptr\u t(\u buf)%AlignTo;
返回值和基本值[(输入)(对齐到偏移)];
}
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;
}
类IWannaBeAligned
{
公众:
IWannaBeAligned()
{
常量intptr_t iThis=(intptr_t)(本);
如果((i为%16)!=0)printf(“错误!对象%p未对齐16字节!(偏移量=%ld)\n”,则此,i为%16);
else printf(“很好,对象%p是16字节对齐的。\n”,this);
}
~IWannaBeAligned()
{
printf(“正在删除对象%p\n”,此文件);
}
char buf[32];//只是给它一个比一个字节更真实的对象大小
};
int main()
{
{
printf(“首先,让我们在没有对齐的固定器的情况下尝试:\n”);
IWannaBeAligned notAligned;
}
printf(“\n”);
{
printf(“现在,我们将使用对齐的固定器:\n)进行尝试”;
对齐的U支架未对齐;
}
返回0;
}
在C++11中,您可以使用。如该页上的示例所示,您的代码可以这样编写:

class alignas(16) C
{
private:
    __m128i m0;
    __m128i m1;
    __m128i cm0;

    int s0;

...

}

保证类成员在本地或静态变量以及本地或静态数组中满足其对齐要求。如果动态分配内存,则可能会遇到问题。我猜您正在尝试使用
std::vector
或类似的方法?如果是,那么就说是。您是正确的,我正在尝试使用e这一个。有什么建议吗?如果不将整个类对齐到至少相同的值,您就不能“对齐成员”。否则,您可以通过类允许的对齐方式替换整个对象,并打破成员对齐方式。(当然,类布局是固定的,不是由每个对象决定的。)让编译器为您填充它。例如,您可以在代码中放置
int size=sizeof(C)
并查看asm输出,从而看到这一点。(请注意,Godbolt的目标是System V ABI,而不是Windows ABI,它们可能并不总是在结构布局上达成一致,但它们将始终填充到所需对齐的倍数,以便阵列的所有元素都具有所需的对齐。)但是,是的,如果您不需要
std::vector
的功能,那么避免它比传递分配对齐存储的自定义分配器更容易。IDK why
std::vector
默认情况下不使用满足对齐要求的分配器:(这是多余的,
\uuum128i
已经是一个16字节对齐的类型。OP的实际问题是试图使用带有
std::vector
的类,即不尊重
alignof(C)
的分配器。任何尊重
alignof(C)
的类都将在没有额外
alignas
的情况下工作。