12

C ++で固定小数点クラスを実装しようとしていますが、パフォーマンスに問題があります。私は問題をfloatタイプの単純なラッパーに減らしましたが、それでも遅いです。私の質問は-コンパイラがそれを完全に最適化できないのはなぜですか?

「float」バージョンは「Float」より50%高速です。なぜ?!

(私はVisual C ++ 2008を使用し、可能なすべてのコンパイラオプションをテストしました。もちろん、構成をリリースします)。

以下のコードを参照してください。

#include <cstdio>
#include <cstdlib>
#include "Clock.h"      // just for measuring time

#define real Float      // Option 1
//#define real float        // Option 2

struct Float
{
private:
    float value;

public:
    Float(float value) : value(value) {}
    operator float() { return value; }

    Float& operator=(const Float& rhs)
    {
        value = rhs.value;
        return *this;
    }

    Float operator+ (const Float& rhs) const
    {
        return Float( value + rhs.value );
    }

    Float operator- (const Float& rhs) const
    {
        return Float( value - rhs.value );
    }

    Float operator* (const Float& rhs) const
    {
        return Float( value * rhs.value );
    }

    bool operator< (const Float& rhs) const
    {
        return value < rhs.value;
    }
};

struct Point
{
    Point() : x(0), y(0) {}
    Point(real x, real y) : x(x), y(y) {}

    real x;
    real y;
};

int main()
{
    // Generate data
    const int N = 30000;
    Point points[N];
    for (int i = 0; i < N; ++i)
    {
        points[i].x = (real)(640.0f * rand() / RAND_MAX);
        points[i].y = (real)(640.0f * rand() / RAND_MAX);
    }

    real limit( 20 * 20 );

    // Check how many pairs of points are closer than 20
    Clock clk;

    int count = 0;
    for (int i = 0; i < N; ++i)
    {
        for (int j = i + 1; j < N; ++j)
        {
            real dx = points[i].x - points[j].x;
            real dy = points[i].y - points[j].y;
            real d2 = dx * dx + dy * dy;
            if ( d2 < limit )
            {
                count++;
            }
        }
    }

    double time = clk.time();

    printf("%d\n", count);
    printf("TIME: %lf\n", time);

    return 0;
}
4

3 に答える 3

4

参照を渡さないようにしてください。クラスは十分に小さいため、参照によって渡すオーバーヘッド(コンパイラが最適化しない場合はオーバーヘッドがあります)は、単にクラスをコピーするよりも高くなる可能性があります。したがって、この...

Float operator+ (const Float& rhs) const
{
   return Float( value + rhs.value );
}

このようなものになります...

Float operator+ (Float rhs) const
{
   rhs.value+=value;
   return rhs;
}

これにより、一時オブジェクトが回避され、ポインターの逆参照の間接参照が回避される場合があります。

于 2011-07-19T09:25:32.633 に答える
4

IMO、それは最適化フラグと関係があります。g++linux-64マシンでプログラムをチェックしました。最適化を行わないと、あなたが言ったのと同じ結果が得られます50%

With keeping the maximum optimization turned ON (i.e. -O4). Both versions are same. Turn on the optimization and check.

于 2011-07-19T09:12:27.003 に答える
2

After further investigation I am thoroughly convinced this is an issue with the optimization pipeline of the compiler. The code generated in this instance is significantly bad in comparison to using a non-encapsulated float. My suggestion is to report this potential issue to Microsoft and see what they have to say about it. I also suggest that you move on to implementing your planned fixed point version of this class as the code generated for integers appears optimal.

于 2011-07-19T09:15:55.890 に答える