5
次のコードは、アラインメントのないAVX命令(MOVAPDではなくMOVUPD)を生成するのはなぜですか?私はVisual Studio 2015でこれをコンパイルしました。データが本当に整列していることをコンパイラにどのように伝えることができますか?_mm256_load_pdがMOVAPDではなくMOVUPDにコンパイルされるのはなぜですか?
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)
それは本当に問題ではありません - 現代のCPUで整列されたデータを非整列ロードを使用するための事実上のペナルティはありませんが - コンパイラの作家はおそらく常に使用する時期を決定するために追加のロジックを持つのではなく、非整列ロードを使用することにしましたアライメントされていないロードに対して –
FWIW gcc *らは正しいことをしているので、これはマイクロソフト固有の癖にすぎません。 –
@PaulR、なぜ仮想という言葉を使用しますか?私が気づいているすべてのペナルティはありません。 'vmovapd'は時代遅れです。 'mvovapd'は' movupd'が他の操作で折り畳むことができないのでネールハムではまだ有用ですが、これは実際には大きな違いがあるのではないかと疑います。たぶんそれはあなたが仮想で意味したものですが、その場合はNehalemにのみ適用され、この答えはNehalem用にはっきりとは作成されていません。 –