24

私は、広範なコンパイル時の計算を伴う C++ プロジェクトに取り組んでいます。長いコンパイル時間は私たちを遅くしています。テンプレート メタ プログラムの最も遅い部分を見つけて最適化するにはどうすればよいですか? (実行時の計算が遅いときは、valgrind のツールなど、多くのプロファイラーから選択できますcallgrind。そのため、デバッグ GCC を作成し、コードをコンパイルしてプロファイリングしようとしましたが、そこから多くを学ぶことはできませんでした。)

私は GCC と Clang を使用していますが、提案は大歓迎です。

Boost のサイトで見つけましprofile_templatesたが、ドキュメントが薄く、jam/bjam ビルド システムが必要なようです。ジャム以外のプロジェクトで使用する方法を示した場合1、私はあなたに賛成票を投じます。https://svn.boost.org/svn/boost/sandbox/tools/profile_templates/は、インスタンス化の数をカウントしているように見えますが、所要時間をカウントするのが理想的です。

1 私たちのプロジェクトは CMake を使用しており、テンプレートのプロファイリングのためだけに Jamfile をハッキングするのに十分なほど小さいです。

4

4 に答える 4

8

私は 2008 年から、テンプレート メタプログラミングを多用するライブラリに取り組んできました。何が最もコンパイル時間を消費するかを理解するためのより優れたツールまたはアプローチが本当に必要です。

私が知っている唯一の手法は、コードを異なるファイルに分割するか、テンプレート定義の本文をコメントアウトするか、テンプレートのインスタンス化を #define マクロでラップし、それらのマクロを一時的に再定義して何もしないという分割統治アプローチです。次に、さまざまなインスタンス化を使用して、または使用せずにプロジェクトを再コンパイルし、絞り込むことができます。

ちなみに、同じコードをより小さなファイルに分割するだけで、コンパイルが速くなる場合があります。私は単に並列コンパイルの可能性について話しているのではありません - シリアルであっても、それでもまだ高速であることがわかりました。ライブラリをコンパイルするときと Boost Spirit パーサーをコンパイルするときの両方で、gcc でこの効果を確認しました。私の理論では、gcc のシンボル解決、オーバーロード解決、SFINAE、または型推論コードの一部は、使用中の型定義またはシンボルの数に関して、O(n log n) または O(n^2) の複雑ささえ持っているというものです。実行ユニットで。

最終的に必要なことは、テンプレートを注意深く調べ、型情報に実際に依存するものとそうでないものを分離し、実際にテンプレート型を必要としないコードの部分で可能な限り型消去と仮想関数を使用することです。コードのその部分を移動できる場合は、ヘッダーから cpp ファイルに何かを取得する必要があります。完璧な世界では、コンパイラがこれを自分で解決できるはずです。このコードを手動で移動して子守する必要はありません。しかし、これは現在のコンパイラの最先端です。

于 2013-04-04T18:19:27.530 に答える
1

古典的な本C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyondには、コンパイル時のコストのプロファイリングに関する 20 ページの付録が付属しています。その付録のグラフを生成するコードを含むコンパニオン CD があります。

別の論文はhttp://aszt.inf.elte.hu/~gsd/s/cikkek/profiling/profile.pdfです。

さらに別の、より手間のかかる方法は、コンパイラ出力から各クラスのインスタンス化の数を数えることです。

于 2013-04-04T18:15:06.590 に答える