c – SSE FP单元是否检测到0.0个操作数?
根据我之前的
question,我的想法是在系数m_a,m_b为1.0或0.0时通过去除计算来优化算法.现在我尝试优化算法并得到一些我无法解释的奇怪结果.
第一个分析仪运行100k样品.从文件(!)读取参数值: b0 = 1.0 b1 = -1.480838022915731 b2 = 1.0 a0 = 1.0 a1 = -1.784147570544337 a2 = 0.854309980957510 第二个分析仪运行相同的100k样本.从文件(!)读取参数值: b0 = 1.0 b1 = -1.480838022915731 b2 = 1.0 a0 = 1.0 a1 = -1.784147570544337 a2 = 0.0 <---只有a2不同! 在图中,左侧的数字(灰色背景)表示所需的CPU周期.因为参数a2 = 0.0的清晰可见的第二次运行要快得多. 我检查了调试和发布代码之间的区别.发布代码更快(正如预期的那样).修改参数a2时,调试和释放代码具有相同的奇怪行为. 然后我检查了ASM代码.我注意到使用了SSE指令.这是有效的,因为我用/ arch:SSE2编译.因此我禁用了SSE.生成的代码不再使用SSE,性能不再依赖于参数值a2(如预期的那样) 因此,我得出的结论是,当使用SSE并且SSE引擎检测到a2为0.0时,它们是某种性能优势,因此省略了过时的乘法和减法.我从来没有听说过这个,并试图找到信息,但没有成功. 那么有人对我的表现结果有解释吗? 为完整起见,这是发布版本的相关ASM代码: 00F43EC0 mov edx,dword ptr [ebx] 00F43EC2 movss xmm0,dword ptr [eax+edi*4] 00F43EC7 cmp edx,dword ptr [ebx+4] 00F43ECA je $LN419+193h (0F43F9Dh) 00F43ED0 mov esi,dword ptr [ebx+4] 00F43ED3 lea eax,[edx+68h] 00F43ED6 lea ecx,[eax-68h] 00F43ED9 cvtps2pd xmm0,xmm0 00F43EDC cmp ecx,esi 00F43EDE je $LN419+180h (0F43F8Ah) 00F43EE4 movss xmm1,dword ptr [eax+4] 00F43EE9 mov ecx,dword ptr [eax] 00F43EEB mov edx,dword ptr [eax-24h] 00F43EEE movss xmm3,dword ptr [edx+4] 00F43EF3 cvtps2pd xmm1,xmm1 00F43EF6 mulsd xmm1,xmm0 00F43EFA movss xmm0,dword ptr [ecx] 00F43EFE cvtps2pd xmm4,xmm0 00F43F01 cvtps2pd xmm3,xmm3 00F43F04 mulsd xmm3,xmm4 00F43F08 xorps xmm2,xmm2 00F43F0B cvtpd2ps xmm2,xmm1 00F43F0F movss xmm1,dword ptr [ecx+4] 00F43F14 cvtps2pd xmm4,xmm1 00F43F17 cvtps2pd xmm2,xmm2 00F43F1A subsd xmm2,xmm3 00F43F1E movss xmm3,dword ptr [edx+8] 00F43F23 mov edx,dword ptr [eax-48h] 00F43F26 cvtps2pd xmm3,xmm3 00F43F29 mulsd xmm3,xmm4 00F43F2D subsd xmm2,xmm3 00F43F31 movss xmm3,dword ptr [edx+4] 00F43F36 cvtps2pd xmm4,xmm0 00F43F39 cvtps2pd xmm3,xmm3 00F43F3C mulsd xmm3,xmm4 00F43F40 movss xmm4,dword ptr [edx] 00F43F44 cvtps2pd xmm4,xmm4 00F43F47 cvtpd2ps xmm2,xmm2 00F43F4B xorps xmm5,xmm5 00F43F4E cvtss2sd xmm5,xmm2 00F43F52 mulsd xmm4,xmm5 00F43F56 addsd xmm3,xmm4 00F43F5A movss xmm4,dword ptr [edx+8] 00F43F5F cvtps2pd xmm1,xmm1 00F43F62 movss dword ptr [ecx+4],xmm0 00F43F67 mov edx,dword ptr [eax] 00F43F69 cvtps2pd xmm4,xmm4 00F43F6C mulsd xmm4,xmm1 00F43F70 addsd xmm3,xmm4 00F43F74 xorps xmm1,xmm1 00F43F77 cvtpd2ps xmm1,xmm3 00F43F7B movss dword ptr [edx],xmm2 00F43F7F movaps xmm0,xmm1 00F43F82 add eax,70h 00F43F85 jmp $LN419+0CCh (0F43ED6h) 00F43F8A movss xmm1,dword ptr [ebx+10h] 00F43F8F cvtps2pd xmm1,xmm1 00F43F92 mulsd xmm1,xmm0 00F43F96 xorps xmm0,xmm0 00F43F99 cvtpd2ps xmm0,xmm1 00F43F9D mov eax,dword ptr [ebp-4Ch] 00F43FA0 movss dword ptr [eax+edi*4],xmm0 00F43FA5 mov ecx,dword ptr [ebp-38h] 00F43FA8 mov eax,dword ptr [ebp-3Ch] 00F43FAB sub ecx,eax 00F43FAD inc edi 00F43FAE sar ecx,2 00F43FB1 cmp edi,ecx 00F43FB3 jb $LN419+0B6h (0F43EC0h) 编辑:按发布代码替换调试ASM代码. 解决方法
SSE上的FP乘法没有早期出局.这是一个完全流水线操作,延迟时间短,因此增加早期输出会使指令退出变得复杂,同时提供零性能优势.在现代处理器上通常具有数据相关执行特性的唯一指令是除法和平方根(忽略次正规,这会影响更广泛的指令).英特尔和AMD都广泛记录了这一点,Agner Fog也独立记录了这一点.
那么为什么你会看到性能的变化呢?最可能的解释是由于输入或结果不正常而遇到失速;这与DSP滤波器和延迟非常相似,就像你拥有的那样.如果没有看到你的代码和输入数据,就不可能确定这是发生了什么,但它是迄今为止最可能的解释.如果是这样,您可以通过在MXCSR中设置DAZ和FTZ位来解决问题. 英特尔文档: AMD 16h指令延迟(excel电子表格): Agner Fog的Intel和AMD指令延迟表: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |