【问题标题】:Performance impact of variadic templates可变参数模板的性能影响
【发布时间】:2013-09-29 22:08:08
【问题描述】:

在我的代码的最新一轮重构中,我用可变参数对应物替换了一堆具有固定数量模板参数的模板类。发现一个特定的性能测试用例出现了大约 20-30% 的性能下降,我感到非常困惑。

几次 git bisect 往返之后,发现了有问题的提交。它实际上是由一个单一的变化组成的

template <typename T, typename U>
class foo {};

template <typename T, typename ... Args>
class foo {};

我已通过实验证实,应用此单一更改会导致上述减速。更令人费解的是,切换编译器版本(从 GCC 4.7 到 GCC 4.8)会将减速发生移动到另一个类似的提交(即,另一个从固定参数切换到可变参数,但在不同的类 bar)。

为了提供一些背景信息,这个特定的性能测试用例是一个非常稀疏的计算机代数问题,它受内存限制,因此很容易受到高效缓存内存利用的影响。这个测试用例一直是我代码中的一个问题点(例如,在 GCC 4.4/4.5 前后,我不得不手动调整管理缓存行大小检测的编译器选项,以获取最大性能)。

有人知道什么会导致这种行为吗?不幸的是,我担心提取简化的测试用例可能非常困难。

编辑

作为参考,这是恢复良好性能行为的提交。不幸的是,它包括为一堆类(而不仅仅是一个类)恢复为非可变代码。我会尝试提出一个更严格的例子。

https://gitorious.org/piranhapp0x/mainline/commit/b952c613b42fe480fe4ed2dfd3e683eb9e38e4cd

【问题讨论】:

  • 真的是空班吗?还是只是简化?
  • @DavidRodríguez-dribeas:只是一个简化。我想明确一点,唯一的变化是切换到可变参数模板声明。其余代码保持不变,不知道类的可变参数和非可变参数版本之间的区别。
  • 如果代码的其余部分保持“不变”,那不是每次有人说U 时都会中断吗?
  • @KerrekSB:好点。在这种情况下,Args 被简单地传递给一个成员对象,该对象确实具有处理可变参数位的所有机制。打破一切的是顶级阶层的变化。
  • @bluescarni:所以变化不是只是上面那个,而是那个和使用可变参数的底层对象......正如你所说的那样,这个问题很糟糕,因为您在询问 {}{} 的性能差异,它们代表相似但不同的代码。 -1

标签: c++ templates gcc c++11 variadic-templates


【解决方案1】:

这是一个广泛的问题,通常的怀疑(就我而言)是在生成的代码中递归处理可变参数模板参数。

您需要检查现在使用可变参数模板参数的方法是否以递归仅在编译时发生,而不是在运行时发生的方式实现。为了给你一些想法,你可能想看看一些例子,例如,this answer of mine。递归发生在编译时,真正的代码是单步转发和扩展。

尽管你写了什么,但我确实希望你实际上必须修改一些代码,否则Args 只能保存一个参数,并且拥有可变参数模板参数完全没有意义 - 请原谅我我错了;)(根据您的评论,它可能会在您将参数包传递给的代码中触发类似上述内容)

【讨论】:

  • 是的,忍者编辑很抱歉。多谢指点,去读一读。我很确定在我的情况下没有太多递归(我只是想避免在我的类的所有上层层次结构中放置一个默认模板参数 - 在基类中创建一个默认参数并在顶部使用可变参数) ,但我会再次检查。
猜你喜欢
  • 2016-12-01
  • 2018-08-07
  • 1970-01-01
  • 2013-10-03
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
  • 1970-01-01
相关资源
最近更新 更多