SSE2命令を含む次のコードが、標準のC++実装よりも乗算の実行速度が遅いのはなぜか疑問に思います。コードは次のとおりです。
m_win = (double*)_aligned_malloc(size*sizeof(double), 16);
__m128d* pData = (__m128d*)input().data;
__m128d* pWin = (__m128d*)m_win;
__m128d* pOut = (__m128d*)m_output.data;
__m128d tmp;
int i=0;
for(; i<m_size/2;i++)
pOut[i] = _mm_mul_pd(pData[i], pWin[i]);
のメモリm_output.data
とinput().data
は_aligned_mallocで割り当てられています。
ただし、2 ^ 25アレイの場合、このコードを実行する時間は、このコードの時間(350ms)と同じです。
for(int i=0;i<m_size;i++)
m_output.data[i] = input().data[i] * m_win[i];
そんなことがあるものか?理論的には50%の時間しかかからないはずですよね?または、SIMDレジスタからm_output.data配列へのメモリ転送のオーバーヘッドは非常に高価ですか?
最初のスニペットの行を置き換えると
pOut[i] = _mm_mul_pd(pData[i], pWin[i]);
に
tmp = _mm_mul_pd(pData[i], pWin[i]);
ここで__m128d tmp;
、コードは非常に高速に実行され、タイマー関数の解像度よりも低くなります。それは、すべてがメモリではなくレジスタに格納されているためですか?
さらに驚くべきことに、デバッグモードでコンパイルすると、SSEコードは93ミリ秒しかかかりませんが、標準の乗算は309ミリ秒かかります。
- デバッグ:93ms(SSE2)/ 309ms(標準乗算)
- リリース:350ms(SSE2)/ 350(標準乗算)
何が起きてる???
QtCreator2.2.1でMSVC2008をリリースモードで使用しています。RELEASE用のコンパイラスイッチは次のとおりです。
cl -c -nologo -Zm200 -Zc:wchar_t- -O2 -MD -GR -EHsc -W3 -w34100 -w34189
これらはDEBUG用です:
cl -c -nologo -Zm200 -Zc:wchar_t- -Zi -MDd -GR -EHsc -W3 -w34100 -w34189
RELEASE vs DEBUGの問題に関する編集:コードのプロファイルを作成したところ、リリースモードでは SSEコードの速度が実際に遅くなっていることに注意してください。 これは、VS2008がオプティマイザで組み込み関数を適切に処理できないという仮説をどういうわけか確認するだけです。Intel VTuneは、DEBUGのSSEループで289ミリ秒、RELEASEモードで504ミリ秒を提供します。うわー...ただすごい...