私が見たすべての場所で、ほとんどすべての点でdouble
はfloat
より優れていると述べています。 float
はJavaのdouble
によって廃止されましたが、なぜそれがまだ使用されているのですか?
私はLibgdxで多くのプログラムを作成し、float
(deltaTimeなど)を使用するように強制しますが、double
の方がストレージとメモリの点で扱いやすいように思えます。
私は floatを使用する場合とdoubleを使用する場合 も読みますが、float
が小数点以下の桁数が多い数値にのみ適している場合、なぜdouble
の多くのバリエーションの1つだけを使用しますか?
フロートの利点がなくなったにもかかわらず、フロートの使用を主張する理由はありますか?すべてを変更するのは大変な作業ですか?
LibGDXは、主にゲーム開発に使用されるフレームワークです。
ゲーム開発では、通常、リアルタイムで大量の数値計算を実行する必要があり、パフォーマンスが問題になる場合があります。そのため、ゲーム開発者は通常、浮動小数点数の精度が十分である場合は常に浮動小数点数を使用します。
この場合、CPUのFPUレジスタのサイズだけを考慮する必要はありません。実際、ゲーム開発における大量の処理はほとんどGPUによって行われ、 GPUは通常、倍精度浮動小数点数ではなく浮動小数点数に対して最適化されます 。
そしてまたあります:
これらはすべて、64ビットダブルではなく32ビットフロートを使用すると2倍の貴重なリソースです。
Floatはdoubleの半分のメモリを使用します。
それらはdoubleよりも精度が低い場合がありますが、多くのアプリケーションは精度を必要としません。それらは、同様のサイズの固定小数点形式よりも広い範囲を持っています。したがって、広い範囲の数値を必要とするが、高い精度は必要とせず、メモリ使用量が重要なニッチを満たします。たとえば、過去に大規模なニューラルネットワークシステムに使用しました。
Javaの外に移動すると、それらは3Dグラフィックスでも広く使用されます。これは、多くのGPUがそれらをプライマリフォーマットとして使用するためです-非常に高価なNVIDIA Tesla/AMD FireProデバイスの外では、GPUで倍精度浮動小数点が非常に遅くなります。
これは、すでに存在する言語/ライブラリ/ [〜#〜] isa [〜#〜]で動作を維持する最大の理由です /etc。
Javaからフロートを取り出した場合、どうなるか考えてみてください。 Libgdx(および他の何千ものライブラリとプログラム)は機能しません。すべてを更新するにはかなりの労力が必要ですが、多くのプロジェクトでは数年かかる可能性があります(下位互換性を壊すPython 2 to Python 3移行)そして、すべてが更新されるわけではありません。保守者がそれらを放棄したために、永久に壊れてしまうものもあります。おそらく、更新したいよりも多くの労力が必要になるため、または更新されなくなったためです可能彼らのソフトウェアがすることになっていたことを達成するために。
64ビットのdoubleはメモリを2倍消費し、ほとんどの場合32ビットのfloatよりも処理が遅くなります(32ビットのfloat機能が使用されることが非常にまれであるか、まったく使用されないという非常にまれな例外は、それらを最適化するための努力が払われなかったためです) 。特殊なハードウェア向けに開発しているのでない限り、近い将来これは発生しません。)
特にあなたに関連する、Libgdxはゲームライブラリです。ゲームは、ほとんどのソフトウェアよりもパフォーマンスに敏感になる傾向があります。また、ゲームグラフィックカード(AMD RadeonやNVIDIA Geforce、FireProやQuadroではない)は、64ビット浮動小数点のパフォーマンスが非常に低くなる傾向があります。 Anandtechの厚意により、一部の AMD's および NVIDIA's で使用可能な倍精度のパフォーマンスと単精度のパフォーマンスを比較しています(2016年の初めに)
AMD
Card R9 Fury X R9 Fury R9 290X R9 290
FP64 1/16 1/16 1/8 1/8
NVIDIA
Card GTX Titan X GTX 980 Ti GTX 980 GTX 780 Ti
FP64 1/32 1/32 1/32 1/24
R9 FuryおよびGTX 900シリーズはR9 200およびGTX 700シリーズよりも新しいため、64ビット浮動小数点の相対的なパフォーマンスが低下していることに注意してください。十分に前に戻ると、R9 200シリーズのように1/8の比率のGTX 580が見つかります。
時間の制約が厳しく、大きなdoubleを使用してもあまり効果がない場合、パフォーマンスの1/32はかなり大きなペナルティです。
他の人がすでに言ったことに加えて、double
(およびlong
)のJava固有の欠点は、64ビットのプリミティブ型への割り当てが保証されていないことです atomic 。 Java言語仕様、Java SE 8 Edition 、660ページから(強調を追加):
Javaプログラミング言語のメモリモデルの目的のために、不揮発性
long
またはdouble
値への単一の書き込みは、2つの別々の書き込みとして扱われます。これにより、スレッドが、ある書き込みからの64ビット値の最初の32ビットと、別の書き込みからの次の32ビットを見る状況が発生する可能性があります。
ああ。
これを回避するには、 volatile
キーワードを使用して64ビット変数を宣言するか、割り当ての周りに他の形式の synchronization を使用する必要があります。
[〜#〜] simd [〜#〜] アーキテクチャは、double
またはfloat
構造体(たとえば、一度に8つのfloat値、または一度に4つのdouble値)。
float
は、特定のCPU(たとえば、特定のモバイルデバイス)でより高速になる場合があります。float
はメモリの使用量が少ないため、巨大なデータセットでは、必要なメモリ(ハードディスク/ RAM)の合計と消費される帯域幅を大幅に削減できます。float
を使用すると、単精度計算の方が倍精度計算と比較して、CPUの消費電力が少なくなる可能性があります(参照を見つけることはできませんが、可能ではないと思われます)。float
は消費する帯域幅が少なく、一部のアプリケーションでは重要です。float
は、doubleと比較して、キャッシュメモリの半分を使用します。float
で十分ですdouble
はとにかくはるかに精度が高いdouble
よりもかなり高速です(それはGPUメーカーはグラフィックスコアの数を増やしようとするため、各コアで可能な限り多くの回路を節約しようとするため、float
を最適化することで、より多くのコアを持つGPUを作成できます)double
を受け入れることができません(3Dレンダリング操作の場合)。double
変数を使用すると、追加の精度が無料で得られると想定できます(パフォーマンスを低下させることなく、さらに精度を高めます)。float
を使用している場合、一部の値は無限になりますが、double
を使用している場合、値が制限される場合があります)float
のみまたはdouble
のみを使用すると、コンパイラーが命令をSIMD化するのに非常に役立ちます。詳細については、以下のPeterCordesからのコメントを参照してください。
言及された他の理由とは別に:
圧力、流量、電流、電圧など、測定データがある場合、これは多くの場合、ADCを備えたハードウェアで行われます。
ADCには通常10または12ビットがあり、14または16ビットはまれです。しかし、16ビットに固執しましょう。フルスケールで測定すると、1/65535の精度になります。つまり、65534/65535から65535/65535への変更は、このステップ-1/65535だけです。およそ1.5E-05です。フロートの精度は約1E-07なので、はるかに優れています。つまり、これらのデータを格納するためにfloat
を使用しても、何も失うことはありません。
浮動小数点数でexcessive計算を行うと、精度の点でdoubles
を使用するよりもパフォーマンスはわずかに低下しますが、多くの場合、その精度は必要ありません。 2 Vまたは2.00002 Vの電圧を測定したばかりです。同様に、この電圧を圧力に変換する場合、3バールまたは3.00003バールがあってもかまいません。