我以前从来没有遇到过这个问题,至少我没有意识到...但是在我的一些代码中,我正在进行一些SIMD向量优化,并且我遇到了一些对齐问题.
以下是我在MSVC(Visual Studio 2022)上能够重现该问题的一些最小代码:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <xmmintrin.h>
_declspec(align(16)) typedef union
{
struct { float x, y, z; };
#if 0
// This works:
float v[4];
#else
// This does not:
__m128 v;
#endif
} vec;
typedef struct
{
vec pos;
vec vel;
float radius;
} particle;
int main(int argc, char **argv)
{
particle *particles=malloc(sizeof(particle)*10);
if(particles==NULL)
return -1;
// intentionally misalign the pointer
((uint8_t *)particles)+=3;
printf("misalignment: %lld\n", (uintptr_t)particles%16);
particles[0].pos=(vec){ 1.0f, 2.0f, 3.0f };
particles[0].vel=(vec){ 4.0f, 5.0f, 6.0f };
printf("pos: %f %f %f\nvel: %f %f %f\n",
particles[0].pos.x, particles[0].pos.y, particles[0].pos.z,
particles[0].vel.x, particles[0].vel.y, particles[0].vel.z);
return 0;
}
我不明白为什么浮点型x/y/z和浮点型[4]的并集与未对齐的内存地址一起工作,但是浮点型x/y/z和__m128
的并集会产生访问冲突.
我知道__m128
类型上有一些额外的对齐规范,但总体联合大小没有变化,而且它也是16字节对齐的,所以这有什么关系呢?
我确实理解内存对齐的重要性,但更奇怪的是,我在分配令人不快的未对齐内存的代码中添加了aligned_malloc
(我在代码中使用了片/区域内存分配器),但它仍然因访问冲突而崩溃,这进一步加剧了我的脱发.