2012-05-05 43 views
4

我剛剛開始使用作者聲稱爲「高度優化」的一段代碼。在某些時候,他們這樣做:定義靜態全局數組以避免在函數中定義它

namespace somename 
{ 
    static float array[N]; 
} 

float Someclass::some_function(std::vector<float>& input) 
{ 
    // use somename::array in some way 
    return result; 
} 

作者並沒有包含在類somename::array因爲與持久性代碼的問題(我們幾乎沒有控制權)。當調用some_function時,該類對數組執行O(N^2)操作。所以,如果我提出array函數調用裏面,

float Someclass::some_function(std::vector<float>& input) 
{ 
    float array[N]; 
    // use somename::array in some way 
    return result; 
} 

是合理的預期性能下降?換句話說,顯而易見的是,在許多不同的系統和編譯器中,作者的優化(使用全局數組而不是一個函數內部)將有助於性能?

+3

你爲什麼認爲這是一個優化? –

+0

你的意思是'系列化'而不是'殺菌'嗎? – sank

+0

@DavidSchwartz好吧,我不確定是否,作者似乎這麼認爲。我假設,因爲它不需要函數每次調用時重建數組。另一方面,大多數現代編譯器可能足夠聰明,可以對此進行優化。 – Shep

回答

2

由於數字物質:

./trial2.out 59.08s用戶0.01S系統88%的CPU 1:07.01總

./trial.out 59.40s用戶0.00S系統99%的CPU 59.556總

的源代碼:http://pastebin.com/YA2WpTSU(帶評價和測試備用的代碼)

所以,沒有什麼區別。編譯:

gcc version 4.1.2 20080704 (Red Hat 4.1.2-46) 

時間的結果,而使用函數內的非靜態數組:

./trial.out 57.32s user 0.04s system 97% cpu 58.810 total 

./trial.out 57.77s user 0.04s system 97% cpu 59.259 total 

所以,再沒有什麼區別。因爲當你使用一個數組時它是你的函數堆棧的一部分而不是堆,所以每次調用這個函數時都沒有預留內存的開銷。如果你使用動態分配(在這種情況下,我懷疑性能會有很大差異),那將是一個完全不同的情況。

+0

非常好。但我試圖解決使用靜態數組(這兩個函數中都使用過),所以真正的比較稍有不同。 – Shep

+0

你是如何在這裏得到時間輸出的? – Shep

+0

我得到了使用UNIX'time'命令的時間輸出:http://linux.die.net/man/1/time –

0

唯一的區別是「數組」是全局分配的(如果聲明爲靜態的),並且如果在函數體中聲明,它將在堆棧上「分配」。這裏真正重要的是你的數組的大小(N)。 如果它是一個大數組,可以將它保留爲靜態,因爲您可能無法在堆棧中聲明它。 第三種選擇是動態分配它(堆,使用新關鍵字)。然而,所有這些假設都不會真正影響函數本身的性能,就像曾經分配過的那樣,這些方法沒有任何開銷。

+0

所以如果數組被分配了_inside_函數,它可能不會影響性能? – Shep

+0

由於它是一個靜態數組,因此它並沒有在函數內完全分配。所以不......它不會影響性能。 –

1

也許你沒有注意到其中的差異,但有一個!使用static關鍵字時,該數組存在於程序的DATA段中,並且它仍然是整個運行時。如果沒有關鍵字static,則數組將駐留在堆棧中,並且每次調用該函數時都會進行初始化。儘管如此,棧版本可能是更好的選擇,因爲它具有更好的局部性,因此緩存未命中率更低。你必須測量你的情況哪個版本更好。在我的情況下(一個數組有69個64位數字和另一個二維數組爲48 * 12個字符),靜態版本明顯更快。

+0

哇......我沒有遵循基準測試的第一條規則:打開_all_優化。使用來自[Rohan's post](http://stackoverflow.com/a/10465028/915501)的代碼進行一些小的修改,我得到的結果幾乎相同。 **但那是與-O0 **。使用-O3時,靜態版本的速度要快2個數量級。 – Shep