13
優化編譯時性能

比方說,我有以下元函數:通過緩存元功能

template <typename T> 
struct make_pair { 
    using type = std::pair< 
     typename std::remove_reference<T>::type, 
     typename std::remove_reference<T>::type 
    >; 
}; 

難道提高編譯速度要做到這一點(或者別的什麼)呢?

template <typename T> 
struct make_pair { 
    using without_reference = typename std::remove_reference<T>::type; 
    using type = std::pair<without_reference, without_reference>; 
}; 

我看到兩種可能性:

  1. 編譯器有每次看到typename std::remove_reference<T>::type時間做一些工作。使用中間別名有一些「緩存」行爲,它允許編譯器只做一次工作。

  2. 編譯時性能是根據編譯器必須完成的模板實例化數量來衡量的。因爲std::remove_reference<T>::type指的是與std::remove_reference<T>::type相同的類型,所以在這兩種情況下都只需要一個模板實例化,因此兩種實現都是等效的WRT編譯時性能。

我認爲B是對的,但我想確定。如果答案證明是特定於編譯器的,我大多會對Clang和GCC的答案感興趣。

編輯

我一個基準測試程序的編制有一些數據的工作。測試程序做這樣的事情:

template <typename ...> struct result;  

template <typename T> 
struct with_cache { 
    using without_reference = typename std::remove_reference<T>::type; 
    using type = result<without_reference, ..., without_reference>; 
}; 

template <typename T> 
struct without_cache { 
    using type = result< 
     typename std::remove_reference<T>::type, 
     ..., 
     typename std::remove_reference<T>::type 
    >; 
{ }; 

using Result = with[out]_cache<int>::type; 

這些都爲項目的10所彙編的平均時間,在result<> 10個000模板參數。

   ------------------------- 
       | g++ 4.8 | clang++ 3.2 | 
----------------------------------------- 
| with cache | 0.1628s | 0.3036s  | 
----------------------------------------- 
| without cache | 0.1573s | 0.3785s  | 
----------------------------------------- 

測試程序由可用腳本here生成。

+4

我認爲沒有任何推測可以取代實際測量。請張貼一些時間數字,然後我們可以創建一個很好的理論來解釋它們。 –

+0

我在clang上看到一段話,說他們爲模板實例而不是鏈表創建哈希表。我不知道他們是誰比較自己。 –

+0

不做記憶的''''編譯器會變得非常慢。 – Yakk

回答

2

我不能說所有編譯器都是如此,但GCC和其他主要編譯器最可能使用memoization。如果你仔細想想,它幾乎必須。

考慮下面的代碼

&f<X, Y>::some_value == &f<X, Y>::some_value 

這是必需是真實的,所以編譯器,以確保它不重複的方法和靜態成員的定義。現在可能有其他的方法來做到這一點,但這只是尖叫我的備忘錄;我沒有看到另一種方式來實現這一點,甚至(授予,我已經很難想到)

當我使用TMP,我期望memoization發生。如果不是這樣,這太痛苦了,太慢了。我唯一看到編譯時間性能差異的方法是:a)使用像Clang這樣的更快的編譯器(它比GCC快3倍)並選擇不同的算法。在我的經驗中,小常數因子在TMP中似乎比在C或C++中更不重要。選擇正確的算法,儘量不要做不必要的工作,儘量保持實例化的數量,並使用一個好的編譯器(MSVC++是真的是慢,遠不符合C++ 11,但GCC和Clang相當不錯);這是你所能做的。

此外,你應該總是犧牲編譯時間來獲得更好的代碼。過早的編譯時間優化比普通的過早優化要困難得多。如果由於某種原因,這種表現對於發展的影響變得非常大,這可能會有例外。但我從來沒有聽說過這種情況。

+1

這個答案並不壞,但它不是我真正想要的。我正在尋找更確定的事情,比如來自GCC或Clang開發人員的確認。 此外,我之所以問這個問題是因爲我一直在研究元編程庫和優化編譯時間是至關重要的。 –