在更新 Autodesk TinkerBox 时,我发现了一个意外的浮点数计算差异。我们的内部开发版本在Windows上运行,而最终目标iOS上运行的版本存在差异(以下信息基于在iPad1上运行的调试构建)。
我们使用 Chipmunk 来满足物理需求。这不太可能是唯一存在此问题的计算,但这是我正在分析的一个特定计算。
我要翻译的内容如下:
据我所知,假设每个指令计算操作数的结果相同,这些计算是相同的。由于某种原因(Visual Studio允许),Xcode不允许我逐条指令地执行,因此我无法缩小哪些指令与英特尔FP单元相比有偏差。
那么,为什么两个CPU在如此简单的计算中的结果会如此不同呢?
我们使用 Chipmunk 来满足物理需求。这不太可能是唯一存在此问题的计算,但这是我正在分析的一个特定计算。
static inline cpFloat
cpvcross(const cpVect &v1, const cpVect &v2)
{
return v1.x*v2.y - v1.y*v2.x;
}
我要翻译的内容如下:
我关注的特定案例,v1
的值为 (0xC0A7BC40 [-5.241729736328125], 0xC0E84C80 [-7.25933837890625]),v2
的值为 (0x428848FB [68.14253997802734],0x42BCBE40 [94.37158203125])。我专注于十六进制版本的值,因为这些是两个平台上都是输入的确切值,通过检查两个平台上 v1
和 v2
的内存位置进行验证。参考资料:方括号中的浮点数值来自将十六进制值放入此网站中获得。
在Windows上结果为0xBA15F8E8 [-0.0005720988847315311],在iOS上结果为0xBA100000 [-0.00054931640625]。当然,差异很小,但如果考虑百分比,它并不小,并且随着时间的推移会积累显示出物理行为的偏差。(请不要建议使用双精度浮点数。当然,这会减慢游戏速度,并且不使用双精度浮点数不是问题的关键。 :) )
参考资料:这是两个平台上的调试版本,代码编译为:
Windows
static inline cpFloat
cpvcross(const cpVect &v1, const cpVect &v2)
{
01324790 push ebp
01324791 mov ebp,esp
01324793 sub esp,0C4h
01324799 push ebx
0132479A push esi
0132479B push edi
0132479C lea edi,[ebp-0C4h]
013247A2 mov ecx,31h
013247A7 mov eax,0CCCCCCCCh
013247AC rep stos dword ptr es:[edi]
return v1.x*v2.y - v1.y*v2.x;
013247AE mov eax,dword ptr [v1]
013247B1 fld dword ptr [eax]
013247B3 mov ecx,dword ptr [v2]
013247B6 fmul dword ptr [ecx+4]
013247B9 mov edx,dword ptr [v1]
013247BC fld dword ptr [edx+4]
013247BF mov eax,dword ptr [v2]
013247C2 fmul dword ptr [eax]
013247C4 fsubp st(1),st
013247C6 fstp dword ptr [ebp-0C4h]
013247CC fld dword ptr [ebp-0C4h]
}
013247D2 pop edi
013247D3 pop esi
013247D4 pop ebx
013247D5 mov esp,ebp
013247D7 pop ebp
013247D8 ret
iOS
invent`cpvcross at cpVect.h:63:
0x94a8: sub sp, sp, #8
0x94ac: str r0, [sp, #4]
0x94b0: str r1, [sp]
0x94b4: ldr r0, [sp, #4]
0x94b8: vldr s0, [r1]
0x94bc: vldr s1, [r1, #4]
0x94c0: vldr s2, [r0]
0x94c4: vldr s3, [r0, #4]
0x94c8: vmul.f32 s1, s2, s1
0x94cc: vmul.f32 s0, s3, s0
0x94d0: vsub.f32 s0, s1, s0
0x94d4: vmov r0, s0
0x94d8: add sp, sp, #8
0x94dc: bx lr
据我所知,假设每个指令计算操作数的结果相同,这些计算是相同的。由于某种原因(Visual Studio允许),Xcode不允许我逐条指令地执行,因此我无法缩小哪些指令与英特尔FP单元相比有偏差。
那么,为什么两个CPU在如此简单的计算中的结果会如此不同呢?