Autodesk TinkerBoxの更新で、Windows で実行される内部専用の開発バージョンと iOS の最終ターゲットで実行されるバージョンとの間で予期しない浮動小数点計算の違いに遭遇しました (次の情報はデバッグに基づいています)。ビルドは iPad で実行されます1)。
物理学のニーズにシマリスを使用します。これがこの問題の唯一の計算である可能性は決してありませんが、それは私が分析していた特定のものです:
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]) です。値の 16 進バージョンに焦点を当てます。これらは両方のプラットフォームの入力である正確な値であり、両方のプラットフォームのメモリ位置を検査することによって検証されるからv1
ですv2
。参考までに、括弧内の浮動小数点値は、このサイトに 16 進値を入力する際に取得したものです。
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
私が知る限り、各命令がオペランドの結果を同じように計算していると仮定すると、これらの計算は同じです。Xcode では、何らかの理由 (Visual Studio では許可されています) で命令ごとにステップ オーバーすることができないため、Intel FP ユニットと比較して逸脱している命令を絞り込むことはできません。
では、なぜこのような単純な計算の結果が 2 つの CPU 間でこれほど異なるのでしょうか?