【问题标题】:Profiling template metaprogram compilation time分析模板元程序编译时间
【发布时间】:2013-03-26 22:40:41
【问题描述】:

我正在开发一个具有大量编译时计算的 C++ 项目。长的编译时间让我们慢了下来。如何找出模板元程序中最慢的部分,以便优化它们? (当我们的运行时计算速度很慢时,我有很多分析器可供选择,例如 valgrind 的 callgrind 工具。所以我尝试构建一个调试 GCC 并分析它来编译我们的代码,但我并没有从中学到很多东西。)

我使用 GCC 和 Clang,但欢迎提出任何建议。

我在 Boost 的网站上找到了profile_templates,但它的文档似乎很少,并且需要 jam/bjam 构建系统。如果你展示了如何在非 Jam 项目中使用它1,我会支持你。 https://svn.boost.org/svn/boost/sandbox/tools/profile_templates/ 似乎可以计算实例的数量,而计算所花费的时间是理想的。

1我们的项目使用 CMake,并且足够小,可以接受将 Jamfile 组合在一起仅用于模板分析。

【问题讨论】:

标签: c++ profiling instantiation template-meta-programming


【解决方案1】:

我知道这是一个老问题,但我想给出一个更新的答案。

有一组基于 clang 的项目可以解决这个特定问题。第一个组件是对 clang 编译器的检测,它生成对编译期间发生的所有模板实例化的完整跟踪,以及计时值和可选的内存使用计数。该工具称为 Templight,可在此处访问(当前需要针对已修补的 clang 源代码树进行编译):

https://github.com/mikael-s-persson/templight

第二个组件是一个转换工具,它允许您将 templight 跟踪转换为其他格式,例如易于解析的基于文本的格式(yaml、xml、文本等)以及更易于可视化的格式,例如graphviz / graphML,更重要的是可以加载到KCacheGrind中的callgrind输出,以可视化和检查模板实例化的元调用图及其编译时成本,例如这个模板实例化配置文件的截图创建boost::container::vector 并使用std::sort 对其进行排序的代码:

在这里查看:

https://github.com/mikael-s-persson/templight-tools

最后,还有另一个相关的项目,它创建了一个交互式 shell 和调试器,以便能够交互式地上下模板实例化图:

https://github.com/sabel83/metashell

【讨论】:

  • 这是模板元编程最棒的事情......我不再需要猜测发生了什么......我真的可以看到它!
  • @Mikael Persson Ty 为这个很棒的项目,虽然 templight-tools 似乎有点过时了,有集成 cmake 3 的计划吗?
【解决方案2】:

经典书籍C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond 附带一个关于分析编译时成本的 20 页附录。它有一张附带的 CD,其中包含生成该附录中的图表的代码。

另一篇论文是http://aszt.inf.elte.hu/~gsd/s/cikkek/profiling/profile.pdf,也许对你有用。

另一种但更费力的方法是从编译器输出中计算每个类的 number of instantiations

【讨论】:

    【解决方案3】:

    自 2008 年以来,我一直致力于开发一个大量使用模板元编程的库。确实需要更好的工具或方法来了解消耗最多编译时间的内容。

    我所知道的唯一技术是分而治之的方法,要么将代码分成不同的文件,注释掉模板定义的主体,要么将模板实例包装在#define 宏中并临时重新定义这些宏以不执行任何操作。然后,您可以重新编译带有和不带有各种实例化的项目并缩小范围。

    顺便说一句,只是将相同的代码分成更多、更小的文件可能会使其编译速度更快。我不仅仅是在谈论并行编译的机会——即使是串行的,我观察到它仍然更快。我在编译库时和编译 Boost Spirit 解析器时都在 gcc 中观察到了这种效果。我的理论是,gcc 中的一些符号解析、重载解析、SFINAE 或类型推断代码相对于类型定义或符号的数量具有 O(n log n) 甚至 O(n^2) 复杂性在执行单元中。

    最终,您需要做的是仔细检查您的模板,并将真正依赖于类型信息的部分与不依赖于类型信息的部分区分开来,并在实际上不需要模板的代码部分尽可能使用类型擦除和虚函数类型。您需要将内容从标题中取出并放入 cpp 文件 如果 那部分代码可以移动。在一个完美的世界里,编译器应该能够自己解决这个问题——你不应该手动移动这段代码来照看它——但这是我们今天拥有的编译器的最新技术。

    【讨论】:

      【解决方案4】:

      http://www.cs.uoregon.edu/research/tau/about.php 可能是您对模板化实体感兴趣的内容,它显示了每个实例化所花费的时间分解。其他数据包括每个函数被调用了多少次,每个函数调用了多少个分析函数,以及每次调用的平均包含时间是多少

      【讨论】:

      • 据我所知,它只计算 runtime 的每个实例化所花费的时间。这不是 OP 所追求的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 2010-10-28
      • 2011-06-26
      相关资源
      最近更新 更多