2011-07-19 39 views
11

我想在C++中實現一個定點類,但是我遇到了性能問題。我已經將問題簡化爲浮點類型的簡單包裝,並且它仍然很慢。我的問題是 - 爲什麼編譯器無法完全優化它?如何在C++中優化一個簡單的數字類型包裝類?

「浮動」版本比「浮動」快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; 
} 
+2

你打開了最大優化標誌嗎?當你把它們打開時,我看到魔法發生了。 – iammilind

+0

生成程序集並檢查差異所在的位置... –

+0

您可以嘗試將所有方法明確標記爲「內聯」 –

回答

4

IMO,它與優化標誌做。我在g ++ linux-64機器上檢查了你的程序。沒有任何優化,它會給出與你告訴哪個更少的結果相同的結果。

保持最大優化開啓(即-O4)。兩個版本都是一樣的。打開優化並檢查。

+1

我已經安裝了GCC,實際上它運行良好!對於GCC,時間爲1.13秒,而VC++爲1.70秒(浮點)或2.58秒(浮點)。我還發現,直接將'dx * dx + dy * dy'移動到該條件會使VC++的性能提高21%! VC++如何優化如此糟糕?我開啓了所有可能的優化選項並測試了許多不同的組合。 –

+0

哇......當我從'Win32'切換到'x64'平臺時,執行時間從2.58秒降到了0.77秒! 'float'和'Float'也是一樣的。 –

2

經過進一步調查,我深信這是編譯器優化管道的問題。與使用非封裝的float相比,在這種情況下生成的代碼顯着爲。我的建議是向微軟報告這個潛在問題,並看看他們對此有何評論。我還建議您繼續實施此類的計劃定點版本,因爲爲整數生成的代碼看起來最佳。

4

嘗試不是通過引用。你的類足夠小,以至於通過引用傳遞它的開銷(如果編譯器沒有優化它的話會有開銷),可能比只複製類要高。因此,這...

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

變成這樣的事情...

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

避免了臨時對象,並且可以避免一個指針引用的一些間接。

+2

我試過了 - 不起作用。它甚至增加了59%的時間。 –