3

興味があったので、ちょっとしたベンチマークを行って、intorなどのプリミティブ型floatとユーザー型の間のパフォーマンス デルタを特定しました。

テンプレート クラスVarを作成し、いくつかのインライン算術演算子を作成しました。Varテストは、プリミティブとベクターの両方に対してこのループをループすることで構成されていました。

for (unsigned i = 0; i < 1000; ++i) {
    in1[i] = i;
    in2[i] = -i;
    out[i] = (i % 2) ? in1[i] + in2[i] : in2[i] - in1[i];
}

私は結果に非常に驚いていました.私のVarクラスはほとんどの場合高速であることがわかりました.intのループは平均してクラスで約5700ナノ秒短縮されました. 3000 回の実行のうち、int は 11 倍速かったのに対し、Var2989 倍高速でした。と同様の結果が得られますfloat。ここで、Varは 2991 回の実行よりも 15100 ナノ秒高速です。

プリミティブ型は高速であるべきではありませんか?

編集: コンパイラはかなり古い mingw 4.4.0 です。ビルド オプションは QtCreator のデフォルトであり、最適化はありません。

qmake call: qmake.exe C:\...\untitled15.pro -r -spec win32-g++ "CONFIG+=release"

OK、完全なソースを投稿、プラットフォームは 64 ビット Win7、4 GB DDR2-800、Core2Duo@3Ghz

#include <QTextStream>
#include <QVector>
#include <QElapsedTimer>

template<typename T>
class Var{
public:
    Var() {}
    Var(T val) : var(val) {}

    inline T operator+(Var& other)
    {
        return var + other.value();
    }

    inline T operator-(Var& other)
    {
        return var - other.value();
    }

    inline T operator+(T& other)
    {
        return var + other;
    }

    inline T operator-(T& other)
    {
        return var - other;
    }

    inline void operator=(T& other)
    {
        var = other;
    }

    inline T& value()
    {
        return var;
    }

private:
    T var;
};

int main()
{
    QTextStream cout(stdout);
    QElapsedTimer timer;

    unsigned count = 1000000;

    QVector<double> pin1(count), pin2(count), pout(count);
    QVector<Var<double> > vin1(count), vin2(count), vout(count);

    unsigned t1, t2, pAcc = 0, vAcc = 0, repeat = 10, pcount = 0, vcount = 0, ecount = 0;
    for (int cc = 0; cc < 5; ++cc)
    {
        for (unsigned c = 0; c < repeat; ++c)
        {
            timer.restart();
            for (unsigned i = 0; i < count; ++i)
            {
                pin1[i] = i;
                pin2[i] = -i;
                pout[i] = (i % 2) ? pin1[i] + pin2[i] : pin2[i] - pin1[i];
            }
            t1 = timer.nsecsElapsed();
            cout << t1 << endl;

            timer.restart();
            for (unsigned i = 0; i < count; ++i)
            {
                vin1[i] = i;
                vin2[i] = -i;
                vout[i] = (i % 2) ? vin1[i] + vin2[i] : vin2[i] - vin1[i];
            }
            t2 = timer.nsecsElapsed();
            cout << t2 << endl;;
            pAcc += t1;
            vAcc += t2;
        }

        pAcc /= repeat;
        vAcc /= repeat;
        if (pAcc < vAcc) {
            cout << "primitive was faster" << endl;
            pcount++;
        }
        else if (pAcc > vAcc) {
            cout << "var was faster" << endl;
            vcount++;
        }
        else {
            cout << "amazingly, both are equally fast" << endl;
            ecount++;
        }

        cout << "Average for primitive type is " << pAcc << ", average for Var is " << vAcc << endl;

    }
    cout << "int was faster " << pcount << " times, var was faster " << vcount << " times, equal " << ecount << " times, " << pcount + vcount + ecount << " times ran total" << endl;
}

比較的、float の場合、Var クラスは float よりも 6 ~ 7% 高速で、int は約 3% です。

また、元の 1000 ではなく 10 000 000 のベクトル長でテストを実行しましたが、結果は依然として一貫しており、クラスを支持しています。

4

2 に答える 2

2

QVector置き換えてstd::vector-O2最適化レベルでは、GCC によって生成された 2 つのタイプのコードは、命令ごとにまったく同じです。

QtVector置換がなければ、生成されるコードは異なりますが、プリミティブ型と非プリミティブ型で実装が異なることを考えると、驚くことではありません ( を参照しQTypeInfo<T>::isComplexてくださいqvector.h)。

更新isComplexlinner oop、つまり測定された部分には影響しないようです。ループ コードは、わずかではありますが、2 つのタイプで異なります。違いはGCCによるもののようです。

于 2012-06-06T15:37:01.997 に答える