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

标签 c visual-studio alignment avx

为什么以下代码会导致未对齐的 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
}

float 类型的类似解决方案:

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 <immintrin.h>

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);
}

关于c - 为什么 _mm256_load_pd 编译为 MOVUPD 而不是 MOVAPD?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36709096/

相关文章:

c++ - Asio 编译器错误(Win7 64 位 + VC11)

html - CSS居中对齐

c - GCC 11.2.0 或 Apple Clang 13.0.0 (clang-1300.0.29.30) 关于应用于 VLA 参数的 const 是否正确?

C strtok 解析复杂字符串

visual-studio - 链接到 VS 中的静态 0MQ 库

c++ - 如何在 MSVS 监 window 口中显示多字符常量?

android - 水平对齐 ImageView 和 EditText

android - 如何在 Android 中显示 Windows 8 风格的图像

c - 字符串(命令行)如何存储在 char**argv 和 int *argv 中?

c - 段错误(核心转储)错误 C linux 套接字