C++レベルでの並列化
Blackswordさんのコメントより。
私のコードを見れば判ると思いますがベクトル化と同時実行を期待した並列化の2つで 速度を稼いでいます。
にひっかかって実験してみる。
最初はBlackswordさんのコードよりもってきたコード。
int test (float* data, float* data2, float* data3) { int i = 0; __m128 XMM0, XMM1, XMM2, XMM3; XMM0 = PM128(&data[i ]); XMM1 = PM128(&data[i+ 4]); XMM2 = PM128(&data[i+ 8]); XMM3 = PM128(&data[i+12]); XMM0 = _mm_mul_ps(XMM0, PM128(&data2[i ])); XMM1 = _mm_mul_ps(XMM1, PM128(&data2[i+ 4])); XMM2 = _mm_mul_ps(XMM2, PM128(&data2[i+ 8])); XMM3 = _mm_mul_ps(XMM3, PM128(&data2[i+12])); PM128(&data3[i ]) = XMM0; PM128(&data3[i+ 4]) = XMM1; PM128(&data3[i+ 8]) = XMM2; PM128(&data3[i+12]) = XMM3; return 0; }
でこれのgcc-4.0.0 -march=athlon-xp -O3 -Sでの結果。
test: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax movl 8(%ebp), %edx movl 16(%ebp), %ecx movaps (%eax), %xmm3 movaps 16(%eax), %xmm2 movaps 32(%eax), %xmm1 movaps 48(%eax), %xmm0 mulps (%edx), %xmm3 xorl %eax, %eax mulps 16(%edx), %xmm2 mulps 32(%edx), %xmm1 mulps 48(%edx), %xmm0 movaps %xmm3, (%ecx) movaps %xmm2, 16(%ecx) movaps %xmm1, 32(%ecx) movaps %xmm0, 48(%ecx) leave ret
こんどは並列化を無視してみた場合。
int test (float* data, float* data2, float* data3) { int i = 0; __m128 XMM0, XMM1, XMM2, XMM3; XMM0 = PM128(&data[i ]); XMM0 = _mm_mul_ps(XMM0, PM128(&data2[i ])); PM128(&data3[i ]) = XMM0; XMM1 = PM128(&data[i+ 4]); XMM1 = _mm_mul_ps(XMM1, PM128(&data2[i+ 4])); PM128(&data3[i+ 4]) = XMM1; XMM2 = PM128(&data[i+ 8]); XMM2 = _mm_mul_ps(XMM2, PM128(&data2[i+ 8])); PM128(&data3[i+ 8]) = XMM2; XMM3 = PM128(&data[i+12]); XMM3 = _mm_mul_ps(XMM3, PM128(&data2[i+12])); PM128(&data3[i+12]) = XMM3; return 0; }
同じくgcc-4.0.0 -march=athlon-xp -O3 -Sでの結果。
test: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax movl 8(%ebp), %ecx movl 16(%ebp), %edx movaps (%eax), %xmm0 mulps (%ecx), %xmm0 movaps %xmm0, (%edx) movaps 16(%eax), %xmm0 mulps 16(%ecx), %xmm0 movaps %xmm0, 16(%edx) movaps 32(%eax), %xmm0 mulps 32(%ecx), %xmm0 movaps %xmm0, 32(%edx) movaps 48(%eax), %xmm0 xorl %eax, %eax mulps 48(%ecx), %xmm0 movaps %xmm0, 48(%edx) leave ret
なるほど、並列化は自分でしないといけないのね。
xmmintrin.hで嬉しいのはレジスタの割当てぐらいなもんですか。
ということはまだまだ最適化の余地はあるなぁ。