web-dev-qa-db-ja.com

代わりにdoubleが主に推奨されているのに、なぜfloatがJava言語の一部であるのですか?)

私が見たすべての場所で、ほとんどすべての点でdoublefloatより優れていると述べています。 floatはJavaのdoubleによって廃止されましたが、なぜそれがまだ使用されているのですか?

私はLibgdxで多くのプログラムを作成し、float(deltaTimeなど)を使用するように強制しますが、doubleの方がストレージとメモリの点で扱いやすいように思えます。

私は floatを使用する場合とdoubleを使用する場合 も読みますが、floatが小数点以下の桁数が多い数値にのみ適している場合、なぜdoubleの多くのバリエーションの1つだけを使用しますか?

フロートの利点がなくなったにもかかわらず、フロートの使用を主張する理由はありますか?すべてを変更するのは大変な作業ですか?

84
Eames

LibGDXは、主にゲーム開発に使用されるフレームワークです。

ゲーム開発では、通常、リアルタイムで大量の数値計算を実行する必要があり、パフォーマンスが問題になる場合があります。そのため、ゲーム開発者は通常、浮動小数点数の精度が十分である場合は常に浮動小数点数を使用します。

この場合、CPUのFPUレジスタのサイズだけを考慮する必要はありません。実際、ゲーム開発における大量の処理はほとんどGPUによって行われ、 GPUは通常、倍精度浮動小数点数ではなく浮動小数点数に対して最適化されます

そしてまたあります:

  • メモリバス帯域幅(RAM、CPU、GPU間でデータをシャベルで高速に転送できる速度)
  • CPUキャッシュ(以前のものをそれほど必要としません)
  • RAM
  • VRAM

これらはすべて、64ビットダブルではなく32ビットフロートを使用すると2倍の貴重なリソースです。

169
Philipp

Floatはdoubleの半分のメモリを使用します。

それらはdoubleよりも精度が低い場合がありますが、多くのアプリケーションは精度を必要としません。それらは、同様のサイズの固定小数点形式よりも広い範囲を持っています。したがって、広い範囲の数値を必要とするが、高い精度は必要とせず、メモリ使用量が重要なニッチを満たします。たとえば、過去に大規模なニューラルネットワークシステムに使用しました。

Javaの外に移動すると、それらは3Dグラフィックスでも広く使用されます。これは、多くのGPUがそれらをプライマリフォーマットとして使用するためです-非常に高価なNVIDIA Tesla/AMD FireProデバイスの外では、GPUで倍精度浮動小数点が非常に遅くなります。

57
Jules

下位互換性

これは、すでに存在する言語/ライブラリ/ [〜#〜] 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はかなり大きなペナルティです。

48
8bittree

原子操作

他の人がすでに言ったことに加えて、double(およびlong)のJava固有の欠点は、64ビットのプリミティブ型への割り当てが保証されていないことです atomicJava言語仕様、Java SE 8 Edition 、660ページから(強調を追加):

17.7 doubleおよびlongの非アトミック処理

Javaプログラミング言語のメモリモデルの目的のために、不揮発性longまたはdouble値への単一の書き込みは、2つの別々の書き込みとして扱われます。これにより、スレッドが、ある書き込みからの64ビット値の最初の32ビットと、別の書き込みからの次の32ビットを見る状況が発生する可能性があります。

ああ。

これを回避するには、 volatile キーワードを使用して64ビット変数を宣言するか、割り当ての周りに他の形式の synchronization を使用する必要があります。

36
Kevin J. Chase

[〜#〜] simd [〜#〜] アーキテクチャは、doubleまたはfloat構造体(たとえば、一度に8つのfloat値、または一度に4つのdouble値)。

パフォーマンスに関する考慮事項の概要

  • floatは、特定のCPU(たとえば、特定のモバイルデバイス)でより高速になる場合があります。
  • floatはメモリの使用量が少ないため、巨大なデータセットでは、必要なメモリ(ハードディスク/ RAM)の合計と消費される帯域幅を大幅に削減できます。
  • floatを使用すると、単精度計算の方が倍精度計算と比較して、CPUの消費電力が少なくなる可能性があります(参照を見つけることはできませんが、可能ではないと思われます)。
  • floatは消費する帯域幅が少なく、一部のアプリケーションでは重要です。
  • SIMDアーキテクチャは、通常、同じ量の2倍ものデータを処理することがあります。
  • floatは、doubleと比較して、キャッシュメモリの半分を使用します。

精度に関する考慮事項の概要

  • 多くのアプリケーションではfloatで十分です
  • doubleはとにかくはるかに精度が高い

互換性に関する考慮事項

  • データをGPUに送信する必要がある場合(たとえば、 OpenGL またはその他のレンダリングAPIを使用するビデオゲームの場合)、浮動小数点形式はdoubleよりもかなり高速です(それはGPUメーカーはグラフィックスコアの数を増やしようとするため、各コアで可能な限り多くの回路を節約しようとするため、floatを最適化することで、より多くのコアを持つGPUを作成できます)
  • 古いGPUと一部のモバイルデバイスは、内部フォーマットとしてdoubleを受け入れることができません(3Dレンダリング操作の場合)。

一般的なヒント

  • 最近のデスクトッププロセッサ(およびおそらくモバイルプロセッサのかなりの数)では、スタックで一時的なdouble変数を使用すると、追加の精度が無料で得られると想定できます(パフォーマンスを低下させることなく、さらに精度を高めます)。
  • 必要以上の精度を使用しないでください(本当に必要な精度がわからない場合があります)。
  • 値の範囲によって強制される場合があります(floatを使用している場合、一部の値は無限になりますが、doubleを使用している場合、値が制限される場合があります)
  • floatのみまたはdoubleのみを使用すると、コンパイラーが命令をSIMD化するのに非常に役立ちます。

詳細については、以下のPeterCordesからのコメントを参照してください。

3
CoffeDeveloper

言及された他の理由とは別に:

圧力、流量、電流、電圧など、測定データがある場合、これは多くの場合、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バールがあってもかまいません。

0
glglgl