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>; 
}; 

は、私は2つの可能性を参照してください。

  1. コンパイラはいくつかの仕事にそれがtypename std::remove_reference<T>::type見たびに行う必要があります。中間エイリアスを使用すると、コンパイラーが何らかの作業を一度しか行うことができない、ある種の「キャッシング」動作があります。

  2. コンパイル時のパフォーマンスは、コンパイラが実行する必要があるテンプレートのインスタンシエーションの数によって測定されます。 std::remove_reference<T>::typestd::remove_reference<T>::typeと同じ型を参照するため、両方の場合に必要なテンプレートインスタンシエーションは1つだけなので、どちらの実装も同等の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; 

これらはresult<>で10個の000テンプレートパラメータを持つプログラムのコンパイル10、の平均時間です。

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

テストプログラムは、利用可能なスクリプトhereによって生成されます。

+4

実際の計測に代わるものではないと思う。いくつかのタイミングの数字を投稿して、それを説明する素晴らしい理論を作成してください。 –

+0

私は、リンクリストの代わりにテンプレートのインスタンス化のためにハッシュテーブルを作成するというclangの話を見ました。私は彼らが自分を誰と比較しているのか分かりません。 –

+0

memoizationを行わない 'template'コンパイラは、非常に遅くなるでしょう。 – Yakk

答えて

2

これはすべてのコンパイラに当てはまるとは言えませんが、GCCや他の主要なコンパイラのほとんどはmemoizationを使用しています。あなたがそれについて考えるなら、それはほとんどの場合です。

はこれが本当であることが必要なので、コンパイラは、それはメソッドと静的メンバの定義が重複していないことを確認する必要がありますされ、次のコード

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

を考えてみましょう。今これを行う他の方法があるかもしれませんが、これは私にメモを叫ぶだけです。私はこれを実装する別の方法も見当たりません(私はそれについて非常に難しいと思っています)

私はTMPを使うと、私はメモが発生することを期待しています。もしそうでなければ、本当に痛いでしょう。私がコンパイル時のパフォーマンスの大きな違いを見た唯一の方法は、a)Clang(GCCよりも3倍速い)のような高速コンパイラを使用し、異なるアルゴリズムを選択することです。私の経験では、定数定数が小さくても、TMPではCやC++よりも問題が少ないようです。適切なアルゴリズムを選択し、不必要な作業をしないようにしてください。インスタンス化の数を減らして、良いコンパイラを使用してください(MSVC++はです。実際にはですが、C++ 11のコンプライアンスからは遠くありませんがGCCとClangはかなり良いです。これは本当にあなたができるすべてです。

また、より良いコードを得るためには、コンパイル時間を犠牲にしてください。早期のコンパイル時間の最適化は、早すぎる最適化よりも悪い方法です。何らかの理由により、パフォーマンスが開発に大して禁止されている場合は例外があります。しかし、私はこれまでこのような事例は聞いていない。

+1

この回答は悪くありませんが、私が探していたものではありません。私は、GCCまたはClang開発者からの確認のような、より確かなものを探しています。 また、私がこの質問をしてきたのは、ライブラリのメタプログラミングに取り組んできたことと、コンパイル時の最適化が重要なためです。 –

関連する問題