将std :: atomic与对齐的类一起使用

Hay*_*ach 12 c++ sse c++11

我有一个mat4类,一个使用sse内在函数的4x4矩阵.这个类是使用对齐的_MM_ALIGN16,因为它将矩阵存储为一组__m128.问题是,当我声明一个时atomic<mat4>,我的编译器对我大喊:

f:\program files (x86)\microsoft visual studio 12.0\vc\include\atomic(504): error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
Run Code Online (Sandbox Code Playgroud)

这是当我尝试传递任何与_MM_ALIGN16作为函数的参数对齐的类(不使用const &)时得到的相同错误.

如何声明mat4类的原子版?

moc*_*ace 4

MSC 编译器从不支持 x86 堆栈上参数超过 4 个字节的对齐方式,并且没有解决方法。

\n\n

您可以通过编译自行验证这一点,

\n\n
struct A { __declspec(align(4)) int x; }; \nvoid foo(A a) {}                      \n
Run Code Online (Sandbox Code Playgroud)\n\n

相对,

\n\n
// won\'t compile, alignment guarantee can\'t be fulfilled\nstruct A { __declspec(align(8)) int x; };\n
Run Code Online (Sandbox Code Playgroud)\n\n

相对,

\n\n
// __m128d is naturally aligned, again - won\'t compile\nstruct A { __m128d x; };\n
Run Code Online (Sandbox Code Playgroud)\n\n

一般来说,MSC可以通过以下方式得到免除:

\n\n
\n

您无法指定函数参数的对齐方式。

\n\n

对齐 (C++)

\n
\n\n

并且您无法指定对齐方式,因为 MSC 编写者希望保留决定对齐方式的自由,

\n\n
\n

x86 编译器使用不同的方法来对齐堆栈。默认情况下,堆栈是 4 字节对齐的。虽然这样可以节省空间,但您可以看到有些数据类型需要 8 字节对齐,并且为了获得良好的性能,有时需要 16 字节对齐。在某些情况下,编译器可以确定动态 8 字节堆栈对齐是有益的,尤其是当堆栈上存在双精度值时。

\n\n

编译器以两种方式执行此操作。首先,当用户在编译和链接时指定时,编译器可以使用链接时代码生成 (LTCG) 来生成完整程序的调用树。这样,它可以确定调用树中 8 字节堆栈对齐有利的区域,并确定动态堆栈对齐获得最佳回报的调用站点。当函数在堆栈上有双精度数时,使用第二种方法,但无论出于何种原因,尚未进行 8 字节对齐。编译器应用启发式方法(随着编译器的每次迭代而改进)来确定函数是否应该动态地进行 8 字节对齐。

\n\n

IPF、x86 和 x64 上的 Windows 数据对齐

\n
\n\n

因此,只要您将 MSC 与 32 位平台工具集一起使用,这个问题就不可避免。

\n\n

x64 ABI 明确了对齐方式,定义了非平凡的结构或超过一定大小的结构作为指针参数传递。这在ABI 的第 3.2.3 节中进行了详细阐述,MSC 必须实现这一点才能与 ABI 兼容。

\n\n

路径 1:使用另一个 Windows 编译器工具链:GCC 或 ICC。

\n\n

路径 2:迁移到 64 位平台 MSC 工具集

\n\n

路径 3:将用例减少为std::atomic<T>with T=__m128d,因为可以跳过堆栈并直接在 XMM 寄存器中传递变量。

\n