几乎可以肯定。
__m128
movaps
加载/存储它,或将它用作其他SSE指令的内存操作数(如
addps xmm0, [mem]
16字节对齐。
float Elements[4][4]
union
对象,这些对象违反了联合对其最对齐的成员进行足够对齐的要求。
gcc -O3 -march=native
_ M128型
vmovaps
不
vmovups
现代硬件具有高效的未对齐负载支持,但缓存线拆分仍然不理想。指令计数也更糟,因为对于avx,编译器必须使用单独的
movups
addps xmm0,[内存]
在C中,移除
,并使用
_mm_loadu_ps()
进行未对齐的加载。
typedef struct my_mat4 { float Elements[4][4]; } my_mat4;
static inline
__m128 load_vec(const struct my_mat4 *m4, size_t idx) {
_mm_loadu_ps(&m4->Elements[idx][0]);
}
使用GNU C:用未对齐的版本重新定义联合
_ M128型
让python对齐对象是最有效的方法,但如果不这样做,则只需对对象进行一次更改即可编译现有代码:
_ M128型
根据GNU C本机向量定义
in xmmintrin.h#69
.(支持GNU扩展的其他编译器是兼容的,至少clang是兼容的。)
typedef float __m128 attribute ((vector_size (16), may_alias));
标题
已经
定义未对齐的
__m128_u
它还使用
aligned(1)
.我们可以用
aligned(4)
以确保它至少与
float
边界,以防万一。
这仅仅是因为相同向量类型的不同对齐版本是可以自由转换的,所以将其传递给intrinsics的代码编译时不会发出警告(即使在
-Wall
)。
typedef float __attribute((vector_size(16), aligned(4))) unaligned__m128;
// I left out may_alias, only matters if you're using unaligned__m128* to load from non-float data.
// Probably doesn't hurt code-gen if you aren't using unaligned__m128* at all, just objects
//#define __m128 unaligned__m128 // not needed
typedef union my_mat4 {
float Elements[4][4];
unaligned__m128 Rows[4];
} my_mat4;
使用这种类型的函数编译得很好(
gcc8.1 on the Godbolt compiler explorer
)。(你也可以写
m4->Rows[1] + m4->Rows[2]
,即使在C不是C++中,因为GNU C本地向量将C操作符映射到每个元素操作。
__m128 use_row(union my_mat4 *m4) {
__m128 tmp = _mm_add_ps(m4->Rows[1], m4->Rows[2]);
m4->Rows[3] = tmp;
return tmp;
}
-O3
(不-三月),我们得到
movups xmm0, XMMWORD PTR [rdi+32] # unaligned loads
movups xmm1, XMMWORD PTR [rdi+16]
addps xmm0, xmm1
movups XMMWORD PTR [rdi+48], xmm0 # unaligned store
ret
-mavx
-march=haswell
use_row(my_mat4*):
vmovups xmm1, XMMWORD PTR [rdi+32]
vaddps xmm0, xmm1, XMMWORD PTR [rdi+16] # unaligned memory source is ok for AVX
vmovups XMMWORD PTR [rdi+48], xmm0
ret
How to remove "noise" from GCC/clang assembly output?
)。
MAT4_MATH__USE_SSE
struct {int foo; my_mat4 m4; };
my_mat4
如果您已经解决了让Python对齐对象的问题
#include <stdalign.h>
// give the same alignment regardless of whether the macro is defined.
typedef union my_mat4
{
alignas(16) float Elements[4][4];
#ifdef MAT4_MATH__USE_SSE
__m128 Rows[4];
#endif
} my_mat4;
如果不希望在宏未定义时保证对齐,则不执行此操作。