2012-01-17 111 views
1
list<mpz_class> baseFactor; 

1)克++編譯器的優化

int *tab = new int [baseFactor.size()]; //baseFactor.size() ~= 20000 
for(i = 0; i < baseFactor.size(); i++){ 
    cout << tab[i] << endl; 
} 

// Total time: 2.620790 

2)

int size = baseFactor.size(); 
int *tab = new int [size]; //baseFactor.size() ~= 20000 
for(i = 0; i < size; i++){ 
    cout << tab[i] << endl; 
} 

//Total time: 0.366500 

爲什麼g ++編譯器不優化在2碼1))?

+3

我的猜測是,在第一種情況下,編譯器不知道'size()'函數返回的值不會改變,所以它必須在每個循環中調用它。 – 2012-01-17 10:05:47

+0

你是怎麼做時間/分析的?如果緩存溫暖,那麼第二個肯定會加快速度。同樣,檢查生成的ASM,你應該看到很少或沒有改變。 – Necrolis 2012-01-17 10:07:35

+3

你打開了優化? – 2012-01-17 10:07:39

回答

5

根據baseFactor被定義的位置(全局變量?),編譯器可能很難證明size()始終返回相同的值。

如果它不能證明,呼叫不能移出循環。

2

對於第一個優化到第二個,它會要求baseFactor.size()在循環過程中永遠不會改變。

當然,它可能不會,但編譯器知道嗎?

1

A std::listcontainer是一個鏈表,並且計算它的大小可能是昂貴的(O(n)算法,它在最新的C++ 11標準IIRC中發生了變化)。編譯器不知道函數的主體沒有改變,所以它的大小在第一種情況下(在for循環的每次測試中)在每個循環中計算一次,並且在第二種情況下只計算一次。

也許你應該考慮使用std::vector來代替。

+0

所以'std :: list'沒有一個簡單的'size'成員可以返回?這令我失望。 – 2012-01-17 10:23:51

+0

我認爲它在C++ 11中已經發生了變化,並且因爲新的C++標準庫(二進制)與舊版本不兼容。 – 2012-01-17 10:25:54

+1

@MrLister - 'std :: list'具有'splice'功能,可以在不同列表之間移動節點。在C++ 03中,選擇是將'splice'設爲恆定時間,這需要在'size'上進行設置。我相信C++ 11做出了不同的選擇 - *一些*調用splice會花費線性時間。 – 2012-01-17 10:48:49