1. ホーム
  2. c++

[解決済み] 最新のハードウェアにおける浮動小数点演算と整数演算の比較

2022-10-20 21:15:50

質問

私は C++ でパフォーマンス重視の仕事をしていますが、現在、本来は浮動小数点である問題に対して、"より速いからという理由で整数計算を使用しています。これは、まったく多くの厄介な問題を引き起こし、多くの厄介なコードを追加します。

今、私は、浮動小数点計算がどのように遅いかについて、およそ 386 日頃に読んだことを覚えています、そこでは (IRC)、オプションの共同プロセッサがあったと思います。しかし、確かに、指数関数的に複雑で強力な CPU がある現在、浮動小数点または整数計算を行う場合、速度に違いはないのでしょうか? 特に、実際の計算時間は、パイプラインのストールやメイン メモリからのフェッチなどに比べてごくわずかだからです。

正しい答えは、ターゲットとなるハードウェア上でベンチマークを行うことだと思いますが、これをテストする良い方法は何でしょうか。私は 2 つの小さな C++ プログラムを書き、それらの実行時間を Linux 上の "time" と比較しましたが、実際の実行時間はあまりにも可変です (私が仮想サーバー上で実行しているのは役に立ちません)。何百ものベンチマークを実行し、グラフなどを作成するために丸一日を費やす必要はありませんが、相対的な速度の妥当なテストを得るために何かできることはないでしょうか?何かアイデアや考えはありますか?私は完全に間違っているのでしょうか?

私が使用したプログラムは次のとおりですが、これらは決して同一ではありません。

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <time.h>

int main( int argc, char** argv )
{
    int accum = 0;

    srand( time( NULL ) );

    for( unsigned int i = 0; i < 100000000; ++i )
    {
        accum += rand( ) % 365;
    }
    std::cout << accum << std::endl;

    return 0;
}

プログラム2

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <time.h>

int main( int argc, char** argv )
{

    float accum = 0;
    srand( time( NULL ) );

    for( unsigned int i = 0; i < 100000000; ++i )
    {
        accum += (float)( rand( ) % 365 );
    }
    std::cout << accum << std::endl;

    return 0;
}

ありがとうございました。

編集:私が気にしているプラットフォームは、デスクトップ Linux と Windows マシンで動作する通常の x86 または x86-64 です。

編集2(下のコメントから貼り付け)。私たちは現在、広範なコードベースを持っています。本当に私は、「整数計算の方が速いので、float を使用してはならない」という一般論に直面しました - そして、私はこの一般化された仮定を反証する方法 (これが真実である場合) を探しています。私は、すべての作業を行い、その後でそれをプロファイリングすることなしに、私たちのために正確な結果を予測することは不可能であることを理解しています。

とにかく、すべての素晴らしい回答およびヘルプに感謝します。他に何かあれば、遠慮なく追加してください :)。

どのように解決するのですか?

残念ながら、「場合による」としか答えようがありません...。

私の経験では、パフォーマンスには多くの変数があります...特に、整数と浮動小数点演算の間で。 プロセッサーによってパイプラインの長さが異なるため、プロセッサーによって (x86 などの同じファミリーの中でも) 大きく異なります。 また、一部の演算は一般に非常に単純で (たとえば足し算)、プロセッサ内の経路が高速化されていますが、他の演算 (たとえば割り算) には非常に長い時間がかかります。

もう 1 つの大きな変数は、データが存在する場所です。 加算する値がわずかであれば、すべてのデータをキャッシュに格納し、CPU にすばやく送ることができます。 データがすでにキャッシュにある非常に遅い浮動小数点演算は、整数がシステム メモリからコピーされる必要がある整数演算よりも何倍も速くなります。

この質問をされるのは、パフォーマンスが重要なアプリケーションに取り組んでおられるからだと思います。 x86 アーキテクチャ用に開発しており、さらにパフォーマンスが必要な場合は、SSE 拡張機能の使用を検討することをお勧めします。 これは単精度浮動小数点演算を大幅に高速化するもので、同じ演算を複数のデータに対して一度に実行でき、さらにSSE演算のためにレジスタのバンクを別に用意します(※)。 (2 番目の例では、quot;double" の代わりに "float" を使用しているので、単精度の演算を使用していると思われます。).

*注: 古い MMX 命令を使用すると、FPU と同じレジスタを実際に使用するため、FPU と MMX の両方を同時に使用することは不可能であり、プログラムが実際に遅くなります。