我想知道为什么带有 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 数组执行此代码的时间与此代码的时间相同(350 毫秒):
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 代码只需要 93ms而标准乘法需要309ms。
- 调试:93ms (SSE2) / 309ms(标准乘法)
- RELEASE:350ms (SSE2) / 350(标准乘法)
这里发生了什么???
我在发布模式下使用带有 QtCreator 2.2.1 的 MSVC2008。这是我的 RELEASE 编译器开关:
cl -c -nologo -Zm200 -Zc:wchar_t- -O2 -MD -GR -EHsc -W3 -w34100 -w34189
这些是用于调试的:
cl -c -nologo -Zm200 -Zc:wchar_t- -Zi -MDd -GR -EHsc -W3 -w34100 -w34189
编辑 关于 RELEASE 与 DEBUG 问题:我只想指出我分析了代码,而 SSE 代码在发布模式下实际上速度较慢! 这只是以某种方式证实了 VS2008 无法正确处理优化器的内在函数的假设。英特尔 VTune 在 DEBUG 中为 SSE 循环提供了 289 毫秒,在 RELEASE 模式下为我提供了 504 毫秒。哇...只是哇...