2

fma()FMA のパフォーマンス ( in math.h) と単純な乗算および浮動小数点演算の加算を比較しようとしています。テストは簡単です。繰り返し回数が多い場合は、同じ計算を繰り返します。正確な検査のために達成しなければならないことが2つあります。

  1. 時間のカウントに他の計算を含めるべきではありません。
  2. 単純な乗算と加算は FMA に最適化されるべきではありません
  3. 反復は最適化されるべきではありません。つまり、反復は意図したとおりに正確に実行する必要があります。

上記のことを達成するために、私は次のことを行いました:

  1. 関数はインラインで、必要な計算のみが含まれています。
  2. 乗算を最適化しないようにg++-O0オプションを使用しました。(しかし、ダンプファイルを調べると、両方でほぼ同じコードが生成されるようです)
  3. 使用済みvolatile

fma()しかし、結果はほとんど違いがないか、単純な乗算と加算に比べてさらに遅くなります。意図したとおりの結果ですか (つまり、速度の点で実際に違いはありません)、それとも何か間違ったことをしていますか?

仕様

  • Ubuntu 14.04.2
  • G++ 4.8.2
  • Intel(R) Core(TM) i7-4770 (3.4GHz、8MB L3キャッシュ)

マイコード

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <chrono>
using namespace std;
using namespace chrono;

inline double rand_gen() {
    return static_cast<double>(rand()) / RAND_MAX;
}

volatile double a, b, c;
inline void pure_fma_func() {
    fma(a, b, c);
}
inline void non_fma_func() {
    a * b + c;
}


int main() {
    int n = 100000000;

    a = rand_gen();
    b = rand_gen();
    c = rand_gen();

    auto t1 = system_clock::now();
    for (int i = 0; i < n; i++) {
        non_fma_func();
    }
    auto t2 = system_clock::now();
    for (int i = 0; i < n; i++) {
        pure_fma_func();
    }
    auto t3 = system_clock::now();

    cout << "non fma" << endl;
    cout << duration_cast<microseconds>(t2 - t1).count() / 1000.0 << "ms" << endl;
    cout << "fma" << endl;
    cout << duration_cast<microseconds>(t3 - t2).count() / 1000.0 << "ms" << endl;
}
4

1 に答える 1

8

はい、あなたは完全に間違ったことをしています。少なくとも2つの何か。しかし、シンプルにしましょう。

Used g++ -O0 option not to optimize the multiplication

これにより、結果全体が完全に無関係になります。興味深い事実: どちらの場合も、関数呼び出しのコストはおそらく計算のコストよりも高くなります。

基本的に、最適化を有効にしないベンチマークの結果はまったく意味がありません。それらをオフにして、最高のものを期待することはできません。それらは絶対に有効にする必要があります。

第二に、FMA と通常の積和は複雑な状況です。レイテンシとスループットのようなものや、積和が勝者になる可能性があるその他の問題があります。

要するに、ベンチマークはまったくベンチマークではなく、無意味なジャンクを生成するランダムな命令の集まりです。

正確なベンチマークが必要な場合は、実際の使用状況を完全に正確に再現する必要があります。周囲のコード、コンパイラの最適化、シバン全体を含みます。

于 2015-03-23T19:44:44.410 に答える