2016-04-19 16 views
5

Aşağıdaki kod neden hizalı olmayan AVX komutlarını (MOVAPD yerine MOVUPD) alıyor? Bunu Visual Studio 2015'te derledim. Derleyiciye, verilerimin gerçekten uyumlu olduğunu nasıl söyleyebilirim?Neden _mm256_load_pd, MOVAPD yerine MOVUPD olarak derlendi?

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) 
+2

Gerçekten önemli değil - Modern CPU'lar hizalanmış verilerle hizalanmamış yükleri kullanmak için neredeyse hiçbir ceza - derleyici yazarlar muhtemelen sadece zaman ne zaman kullanılacağını belirlemek için ek mantığı sahip ziyade hizalanmamış yükleri kullanmaya karar verdi hizalanmamış yüklere karşı hizalanmış. –

+0

FWIW gcc * et al * doğru olanı yap, bu sadece Microsoft'a özgü bir tuhaflık gibi görünüyor. –

+3

@PaulR, neden sanal kelimeyi kullanıyorsunuz? Hiç bilmediğim bir ceza yoktur. vmovapd eskidir. 'mvovapd' hala nehalem üzerinde yararlıdır çünkü 'movupd' diğer operasyonlarla katlanamaz ama bunun pratikte büyük bir fark yarattığından kuşkuluyum. Belki de sanal olarak kastettiğiniz şey budur ancak bu durumda sadece Nehalem için geçerlidir ve bu cevap Nehalem için açık bir şekilde derlenmemektedir. –

cevap

0

bu sorunu çözmek için bir yol yoktur (o) yerine MOVUPD talimat VMOVDQA (MOVAPD analog kullanmasını sağlar):

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 
} 
şamandıra tipi için

benzer çözüm:

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 
} 

Ancak Visual Studio derleyicisini aldatmak için dinamik olarak ayrılmış işaretçiler kullanmalısınız. Aksi halde derleyici VMOVDQA talimatını kullanmaz.

#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); 
} 
İlgili konular