web-dev-qa-db-ja.com

doubleをfloatよりも高速に使用していますか?

Double値はより高い精度を格納し、floatのサイズの2倍ですが、Intel CPUはfloat用に最適化されていますか?

つまり、二重演算は、+、-、*、および/のフロート演算と同じくらい速いですか、それとも速いですか?

64ビットアーキテクチャの答えは変わりますか?

65
Brent Faust

特に他の操作に対してどの操作が最適化されているかという点では、単一の「Intel CPU」はありません!しかし、それらのほとんどは、CPUレベル(特にFPU内)で、あなたの質問に対する答えです:

ダブル操作は、+、-、*、および/のフロート操作と同じくらいまたは高速ですか?

「はい」です- CPU 内、除算とsqrtは例外です doubleの場合はfloatの場合よりもやや遅い 。 (コンパイラーがスカラーFP mathにSSE2を使用し、すべてのx86-64コンパイラー、およびオプションに依存する一部の32ビットコンパイラーを使用すると仮定します。従来のx87のレジスターの幅は異なり、メモリ内(ロード/ストアで変換)であるため、歴史的にsqrtと除算でさえdoubleの場合と同じくらい遅かったです。

たとえば、Haswellのスループットは8〜14サイクルあたり1つ(データ依存)のdivsdですが、7サイクルあたり1つのdivss(スカラーシングル)スループットです。 x87 fdivは8〜18サイクルのスループットです。 ( https://agner.org/optimize/ の数値。遅延は除算のスループットと相関しますが、スループットの数値よりも高くなります。)

_logf(float)sinf(float)のような多くのライブラリ関数のfloatバージョンは、log(double)sin(double)。正しい精度のビットがはるかに少ないためです。 floatdoubleの完全な精度を得るために、より少ない項で多項式近似を使用できます


ただし、、各番号のメモリを2倍使用することは、キャッシュへの負荷が大きくなり、メモリ帯域幅がいっぱいになり、これらのキャッシュラインをRAMから流出させます。浮動小数点演算のパフォーマンスに関心があるのは、そのような演算を lot するときです。そのため、メモリとキャッシュの考慮事項が重要です。

@Richardの答えは、FP操作( [〜#〜] sse [〜#〜] /SSE2命令;古き良き時代を実行する他の方法もあることを指摘しています。 MMXは整数のみ)、特に各ベクトルレジスタが4つの単精度浮動小数点または2つの倍精度のみをパックできる大量のデータ(「SIMD」、単一命令/複数データ)の単純な演算に適していますones なので、この効果はさらに顕著になります。

最終的には、ベンチマークを行う必要がありますが、私の予測では、合理的な(つまりlarge;-)ベンチマークのために、単精度に固執することの利点があります(仮定すると)もちろん、 need 余分なビットは必要ありません!-)。

72
Alex Martelli

すべての浮動小数点計算がFPU内で実行される場合、いいえ、浮動小数点演算は実際に80ビットで実行されるため、double計算とfloat計算の間に違いはありません。 FPUスタックの精度。 FPUスタックのエントリは、80ビット浮動小数点形式をdoubleまたはfloat浮動小数点形式に変換するために適切に丸められます。 sizeof(double)バイトをRAM対sizeof(float)バイトと移動することだけが速度の違いです。

ただし、ベクトル化可能な計算がある場合は、SSE拡張機能を使用して、2つのfloat計算と同時に4つのdouble計算を実行できます。したがって、SSE命令とXMMレジスタを巧妙に使用すると、floatsのみを使用する計算のスループットを高めることができます。

24
Daniel Trebbien

考慮すべきもう1つのポイントは、GPU(グラフィックカード)を使用している場合です。私は数値的に集中的なプロジェクトで働いていますが、二重に提供される精度は必要ありません。 GPUカードを使用して、処理をさらに高速化します。 CUDA GPUには、doubleをサポートするための特別なパッケージが必要であり、GPUでのローカルRAMの量は非常に高速ですが、非常に少ないです。その結果、floatを使用すると、 GPUに保存します。

さらに別のポイントは記憶です。フロートは、2倍の半分のRAMを使用します。非常に大きなデータセットを処理している場合、これは非常に重要な要素になります。違いは大きいでしょう。

したがって、私が使用しているアプリケーションでは、違いは非常に重要です。

11
Miley

既に存在する素晴らしい答えに__m256?同一命令複数データのファミリー( [〜#〜] simd [〜#〜] )C++組み込み関数はeither4double s並列(例_mm256_add_pd)、または8floats並列(例:_mm256_add_ps)。

これが実際のスピードアップに変換できるかどうかはわかりませんが、それは可能だと思われます SIMDを使用する場合の命令。

10
bobobobo

3.3を2000000000回追加する実験では、結果は次のとおりです。

Summation time in s: 2.82 summed value: 6.71089e+07 // float
Summation time in s: 2.78585 summed value: 6.6e+09 // double
Summation time in s: 2.76812 summed value: 6.6e+09 // long double

したがって、CおよびC++ではdoubleの方が高速でデフォルトです。より移植性が高く、すべてのCおよびC++ライブラリ関数でデフォルトです。 Alos doubleはfloatよりもかなり高い精度を持っています。

Stroustrupでさえ、double over floatを推奨しています:

「単精度、倍精度、および拡張精度の正確な意味は実装定義です。選択が重要な問題に適切な精度を選択するには、浮動小数点計算を十分に理解する必要があります。アドバイスをしたり、時間をかけて学習したり、ダブルを使って最高の結果を期待したりすることができます。」

おそらく、doubleの代わりにfloatを使用する必要がある唯一のケースは、最新のgccを備えた64ビットハードウェア上にある場合です。フロートが小さいため。 doubleは8バイトで、floatは4バイトです。

9
Akash Agrawal

本当に役立つ答えは、あなただけが知ることができるということだけです。シナリオをベンチマークする必要があります。命令およびメモリパターンの小さな変更は、重大な影響を与える可能性があります。

FPUまたはSSEタイプのハードウェアを使用している場合(以前はすべての作業を80ビット拡張精度で実行するため、doubleはより近くなります。後でネイティブ32ビット、すなわちfloatです)重要です。

更新:別の回答に記載されているs/MMX/SSE /。

7
Richard

浮動小数点は通常、汎用CPUの拡張です。したがって、速度は使用するハードウェアプラットフォームに依存します。プラットフォームが浮動小数点をサポートしている場合、違いがあれば驚くでしょう。

2
doron