Double値はより高い精度を格納し、floatのサイズの2倍ですが、Intel CPUはfloat用に最適化されていますか?
つまり、二重演算は、+、-、*、および/のフロート演算と同じくらい速いですか、それとも速いですか?
64ビットアーキテクチャの答えは変わりますか?
特に他の操作に対してどの操作が最適化されているかという点では、単一の「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)
。正しい精度のビットがはるかに少ないためです。 float
対double
の完全な精度を得るために、より少ない項で多項式近似を使用できます
ただし、、各番号のメモリを2倍使用することは、キャッシュへの負荷が大きくなり、メモリ帯域幅がいっぱいになり、これらのキャッシュラインをRAMから流出させます。浮動小数点演算のパフォーマンスに関心があるのは、そのような演算を lot するときです。そのため、メモリとキャッシュの考慮事項が重要です。
@Richardの答えは、FP操作( [〜#〜] sse [〜#〜] /SSE2命令;古き良き時代を実行する他の方法もあることを指摘しています。 MMXは整数のみ)、特に各ベクトルレジスタが4つの単精度浮動小数点または2つの倍精度のみをパックできる大量のデータ(「SIMD」、単一命令/複数データ)の単純な演算に適していますones なので、この効果はさらに顕著になります。
最終的には、ベンチマークを行う必要がありますが、私の予測では、合理的な(つまりlarge;-)ベンチマークのために、単精度に固執することの利点があります(仮定すると)もちろん、 need 余分なビットは必要ありません!-)。
すべての浮動小数点計算がFPU内で実行される場合、いいえ、浮動小数点演算は実際に80ビットで実行されるため、double
計算とfloat
計算の間に違いはありません。 FPUスタックの精度。 FPUスタックのエントリは、80ビット浮動小数点形式をdouble
またはfloat
浮動小数点形式に変換するために適切に丸められます。 sizeof(double)
バイトをRAM対sizeof(float)
バイトと移動することだけが速度の違いです。
ただし、ベクトル化可能な計算がある場合は、SSE拡張機能を使用して、2つのfloat
計算と同時に4つのdouble
計算を実行できます。したがって、SSE命令とXMMレジスタを巧妙に使用すると、float
sのみを使用する計算のスループットを高めることができます。
考慮すべきもう1つのポイントは、GPU(グラフィックカード)を使用している場合です。私は数値的に集中的なプロジェクトで働いていますが、二重に提供される精度は必要ありません。 GPUカードを使用して、処理をさらに高速化します。 CUDA GPUには、doubleをサポートするための特別なパッケージが必要であり、GPUでのローカルRAMの量は非常に高速ですが、非常に少ないです。その結果、floatを使用すると、 GPUに保存します。
さらに別のポイントは記憶です。フロートは、2倍の半分のRAMを使用します。非常に大きなデータセットを処理している場合、これは非常に重要な要素になります。違いは大きいでしょう。
したがって、私が使用しているアプリケーションでは、違いは非常に重要です。
既に存在する素晴らしい答えに__m256?
同一命令複数データのファミリー( [〜#〜] simd [〜#〜] )C++組み込み関数はeither4double
s並列(例_mm256_add_pd
)、または8float
s並列(例:_mm256_add_ps
)。
これが実際のスピードアップに変換できるかどうかはわかりませんが、それは可能だと思われます SIMDを使用する場合の命令。
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バイトです。
本当に役立つ答えは、あなただけが知ることができるということだけです。シナリオをベンチマークする必要があります。命令およびメモリパターンの小さな変更は、重大な影響を与える可能性があります。
FPUまたはSSEタイプのハードウェアを使用している場合(以前はすべての作業を80ビット拡張精度で実行するため、doubleはより近くなります。後でネイティブ32ビット、すなわちfloatです)重要です。
更新:別の回答に記載されているs/MMX/SSE /。
浮動小数点は通常、汎用CPUの拡張です。したがって、速度は使用するハードウェアプラットフォームに依存します。プラットフォームが浮動小数点をサポートしている場合、違いがあれば驚くでしょう。