決定論的な方法での浮動小数点数の処理について
浮動小数点は決定的です。まあ、あるべきです。それは複雑です。
浮動小数点数に関する多くの文献があります。
そして、それらがどのように問題があるのか:
抽象的に。少なくとも、単一のスレッドでは、同じ操作が同じデータで行われ、同じ順序で発生するため、確定的である必要があります。したがって、入力を心配して、順序を変更することから始めることができます。
問題を引き起こすこのような入力の1つは時間です。
まず、常に同じタイムステップを計算する必要があります。時間を測定しないと言っているのではなく、時間の変動がシミュレーションのノイズの原因であるため、物理シミュレーションに時間を渡さないと言っています。
物理シミュレーションに渡さないのに、なぜ時間を測定するのですか?シミュレーションステップをいつ呼び出すべきかを知るために経過時間を測定し、スリープを使用していると仮定して、スリープ時間を測定します。
副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:
- 時間を測定:はい
- シミュレーションで時間を使用:いいえ
さて、命令の並べ替え。
コンパイラf * a + b
は、それがと同じであると判断するb + f * a
可能性がありますが、結果が異なる場合があります。また、fmaddにコンパイルすることもできますし、一緒に発生するそのような複数の行を取得してSIMDで記述することもできます。また、同じ操作を同じ順序で実行したいので、どの操作が実行されるかを制御したいのは当然です。
いいえ、doubleを使用しても節約にはなりません。
特に、ネットワーク全体で浮動小数点数を同期するには、コンパイラとその構成について心配する必要があります。同じことをすることに同意するビルドを取得する必要があります。
おそらく、アセンブリを記述することが理想的です。そのようにして、どの操作を行うかを決定します。ただし、複数のプラットフォームをサポートするには問題になる可能性があります。
副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:
固定小数点数の場合
メモリでの浮動小数点の表現方法により、大きな値は精度を失います。値を小さく保つ(クランプする)ことで問題が軽減されるのは理にかなっています。したがって、大きな速度と大きな部屋はありません。これは、トンネリングのリスクが少ないため、個別の物理を使用できることも意味します。
一方、小さなエラーは累積します。だから、切り捨てます。つまり、スケーリングして整数型にキャストします。そうすれば、何も構築されていないことがわかります。整数型にとどまることができる操作があります。浮動小数点に戻る必要があるときは、スケーリングをキャストして元に戻します。
スケールと言います。アイデアは、1ユニットが実際には2の累乗(たとえば16384)として表されるということです。それが何であれ、それを定数にして使用します。基本的に固定小数点数として使用しています。実際、信頼できるライブラリの適切な固定小数点数をはるかにうまく使用できる場合。
私は切り捨てと言っています。丸めの問題については、キャスト後に取得した値の最後のビットを信頼できないことを意味します。したがって、キャストスケールの前に、必要以上に1つ多くを取得し、後でそれを切り捨てます。
副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:
- 値を小さく保つ:はい
- 慎重な丸め:はい
- 可能な場合は固定小数点数:はい
待って、なぜ浮動小数点が必要なのですか?整数型だけで作業することはできませんか?ああ、そう。三角法と放射。三角法と放射のテーブルを計算し、ソースに焼き付けることができます。または、代わりに固定小数点数を使用する場合を除き、浮動小数点数を使用してそれらを計算するために使用されるアルゴリズムを実装できます。はい、メモリ、パフォーマンス、精度のバランスを取る必要があります。それでも、浮動小数点数を避けて、決定論的であり続けることができます。
オリジナルのPlayStationでそのようなことを行ったことをご存知ですか 私の犬に会ってください、パッチ。
ところで、グラフィックに浮動小数点を使用しないと言っているのではありません。物理学のためだけに。確かに、位置は物理学に依存します。ただし、ご存じのとおり、コライダーはモデルと一致する必要はありません。モデルの切り捨ての結果を見たくありません。
したがって、固定小数点数を使用します。
明確にするために、浮動小数点の動作を指定できるコンパイラを使用でき、それで十分であれば、それを実行できます。それは常にオプションではありません。また、決定論のためにこれを行っています。固定小数点数は、精度に制限があるため、エラーがないという意味ではありません。
「固定小数点数が難しい」ことは、それらを使用しない正当な理由だとは思いません。そして、それらを使用する正当な理由が必要な場合、それは決定論、特にプラットフォーム間の決定論です。
こちらもご覧ください:
補遺:世界のサイズを小さく保つことを提案しています。そうは言っても、OPとJibb Smartの両方は、原点フロートから離れると精度が低下するという点を示します。それは物理学に影響を与え、世界の端よりもはるかに早く見られるでしょう。固定小数点数は、精度が固定されており、どこでも同じように優れています(必要に応じて、悪い場合もあります)。決定論が必要な場合、これは良いことです。また、私たちが通常物理学を行う方法には、小さな変動を増幅する性質があることにも言及したいと思います。バタフライエフェクト-信じられないほどの機械とからくりメーカーの決定論的物理学を参照してください。
物理学を行う別の方法
私は、浮動小数点数の精度の小さな誤差が増幅する理由は、私たちがそれらの数で反復を行っているためだと考えてきました。各シミュレーションステップでは、最後のシミュレーションステップの結果を取得し、それらの処理を行います。エラーの上にエラーを蓄積する。それがあなたのバタフライ効果です。
同じマシンで単一のスレッドを使用する単一のビルドが、同じ入力によって異なる出力を生成するとは思わない。しかし、別のマシンで、または異なるビルドで可能です。
そこでテストするための議論があります。物事がどのように機能するかを正確に決定し、ターゲットハードウェアでテストできる場合、異なる動作をするビルドを出すべきではありません。
ただし、多くのエラーを蓄積する離れて作業しないことについての議論もあります。おそらくこれは、異なる方法で物理学を行う機会です。
ご存知かもしれませんが、連続物理学と離散物理学があり、どちらも各オブジェクトがタイムステップでどれだけ進むかについて機能します。ただし、連続物理学には、さまざまな可能性のある瞬間を調べて衝突が発生したかどうかを調べるのではなく、衝突の瞬間を把握する手段があります。
したがって、私は次のことを提案しています。連続物理学の手法を使用して、各オブジェクトの次の衝突がいつ発生するかを把握します。次に、最も近い衝突の瞬間を取り、その瞬間にすべてがどこにあるかを把握します。
はい、それは単一のシミュレーションステップの多くの仕事です。つまり、シミュレーションはすぐには開始されません...
...ただし、次の衝突がいつ発生するか(または大きなタイムステップで衝突が発生しないこと)がすでにわかっているため、衝突を毎回確認することなく、次のいくつかのシミュレーションステップをシミュレートできます。さらに、シミュレーションが大きなタイムステップに達すると、事前に計算した位置を配置するだけなので、そのシミュレーションで蓄積されたエラーは無関係です。
これで、各シミュレーションステップで衝突をチェックするために使用していた時間バジェットを使用して、見つかった次の衝突を計算できます。つまり、大きなタイムステップを使用して、先にシミュレーションを行うことができます。世界の範囲が制限されていると仮定すると(これは巨大なゲームでは機能しません)、シミュレーションの将来の状態のキューがあり、最後の状態から次の状態に補間する各フレームが必要です。
補間について議論します。ただし、加速があるため、すべてを同じ方法で単純に補間することはできません。代わりに、各オブジェクトの加速度を考慮して補間する必要があります。その点については、大きなタイムステップの場合と同じ方法で位置を更新できます(つまり、同じ動きに対して2つの異なる実装を使用しないため、エラーが発生しにくくなります)。
注:この浮動小数点数を使用している場合、このアプローチでは、オブジェクトが原点から離れるにつれて異なる動作をするという問題は解決しません。ただし、原点から遠ざかるほど精度が失われるのは事実ですが、それでも決定論的です。実際、それが元々それを持ち出さなかった理由です。
補遺
コメントの OPから:
アイデアは、プレイヤーがマシンを何らかの形式(xmlやjsonなど)で保存できるようにして、各ピースの位置と回転が記録されるようにすることです。そのxmlまたはjsonファイルは、別のプレーヤーのコンピューターでマシンを再現するために使用されます。
だから、バイナリ形式はありませんか?つまり、復元された浮動小数点数が元のものと一致するかどうかを心配する必要もあります。参照:フロート精度の再検討:9桁のフロートの移植性