为什么_mm256_load_pd编译为MOVUPD而不是MOVAPD?

为什么以下代码会产生未对齐的AVX指令(MOVUPD而不是MOVAPD)? 我在Visual Studio 2015上编译了这个。如何告诉编译器我的数据确实是对齐的?

const size_t ALIGN_SIZE = 64; const size_t ARRAY_SIZE = 1024; double __declspec(align(ALIGN_SIZE)) a[ARRAY_SIZE]; double __declspec(align(ALIGN_SIZE)) b[ARRAY_SIZE]; //Calculate the dotproduct __m256d ymm0 = _mm256_set1_pd(0.0); for (int i = 0; i < ARRAY_SIZE; i += 8) { __m256d ymm1 = _mm256_load_pd(a + i); __m256d ymm2 = _mm256_load_pd(b + i); __m256d ymm3 = _mm256_mul_pd(ymm1, ymm2); ymm0 = _mm256_add_pd(ymm3, ymm0); __m256d ymm4 = _mm256_load_pd(a + i + 4); __m256d ymm5 = _mm256_load_pd(b + i + 4); __m256d ymm6 = _mm256_mul_pd(ymm4, ymm5); ymm0 = _mm256_add_pd(ymm6, ymm0); } Assembly of the loop: 00007FF7AC7A1400 vmovupd ymm1,ymmword ptr [rbp+rax*8+2020h] 00007FF7AC7A1409 vmulpd ymm3,ymm1,ymmword ptr [rbp+rax*8+20h] 00007FF7AC7A140F vmovupd ymm2,ymmword ptr [rbp+rax*8] 00007FF7AC7A1415 vmulpd ymm0,ymm2,ymmword ptr b[rax*8] 00007FF7AC7A141E add r8d,8 00007FF7AC7A1422 movsxd rax,r8d 00007FF7AC7A1425 vaddpd ymm1,ymm0,ymm4 00007FF7AC7A1429 vaddpd ymm4,ymm1,ymm3 00007FF7AC7A142D cmp rax,400h 00007FF7AC7A1433 jb main+70h (07FF7AC7A1400h) 

有办法解决这个问题(它允许使用指令VMOVDQA(MOVAPD的模拟)而不是MOVUPD):

 inline __m256d Load(const double * p) { #ifdef _MSC_VER return _mm256_castsi256_pd(_mm256_load_si256((__m256i*)p)); #else return _mm256_load_pd(p); #endif } 

浮动类型的类比解决方案:

 inline __m256 Load(const float * p) { #ifdef _MSC_VER return _mm256_castsi256_ps(_mm256_load_si256((__m256i*)p)); #else return _mm256_load_ps(p); #endif } 

但是为了欺骗Visual Studio编译器,你必须使用动态分配的指针。 否则编译器不使用VMOVDQA指令。

 #include  int main() { float * ps = (float*)_mm_malloc(40, 32); double * pd = (double*)_mm_malloc(40, 32); __m256 s = Load(ps); //00007FF79FF81325 vmovdqa ymm1,ymmword ptr [rdi] __m256d d = Load(pd); //00007FF79FF8132F vmovdqa ymm0,ymmword ptr [rax] _mm256_storeu_ps(ps, s); _mm256_storeu_pd(pd, d); _mm_free(ps); _mm_free(pd); }