【问题标题】:Does template class specialization/explicit instantiation improves compilation/linker speed?模板类专业化/显式实例化是否提高了编译/链接器速度?
【发布时间】:2011-01-12 10:43:49
【问题描述】:

假设以下模板类在一个项目中大量使用,其中大部分是 int 作为类型名,并且自引入该类以来链接器速度明显变慢。

template <typename T>
class MyClass
{
void Print()
{
    std::cout << m_tValue << std::endl;;
}
T m_tValue;
}

定义一个类专业化有利于编译速度吗? 例如。

template <>
class MyClass<int>
{
void Print()
{
    std::cout << m_tValue << std::endl;;
}
int m_tValue;
}

或者显式实例化是否提供了更好的解决方案? 例如。

template class MyClass<int>;

【问题讨论】:

  • @sbi,你是对的,谢谢,我已经编辑了我的答案,你能重新评估它的正确性吗?
  • 好吧,我应该说我已经编辑了我的问题,而不是我的答案;)

标签: c++ templates linker compilation specialization


【解决方案1】:

在 C++0x 中,您将能够使用外部模板,以便模板的实例化只发生一次,就像外部变量一样。

这应该有助于编译时间,因为编译器不必在每次看到模板时都使用其参数实例化模板。

我还没有弄清楚我将如何在我自己的项目中使用这个功能,但是任何可以帮助编译时间的东西对我来说都是一个加分项。

http://www2.research.att.com/~bs/C++0xFAQ.html#extern-templates

【讨论】:

    【解决方案2】:

    通过使程序更复杂——更长,并且在调用点需要更多的消除歧义——一般来说,编译器会变得更慢而不是更快。

    但是,除非您自动生成大量此类专业,否则这不太可能成为大问题。此外,编译器之间的性能各不相同 - 您始终可以自己进行测试(我希望如果没有严格的测试和大量的测试运行,差异会很小,不会很明显)。

    链接器速度可能会降低,因为模板在所有引用它的编译模块中都被声明为“内联”(尽管不一定是内联的)。发生这种情况时,您将在整个地方复制一个方法,并且链接器会得到更多的工作。相比之下,仅在标头中声明且仅在一处定义的“正常”函数将导致仅编译一个函数,因此链接器(和编译器)的函数更少。根据链接时代码生成等选项,这可能非常重要或根本不重要。

    【讨论】:

      【解决方案3】:

      我们发现模板可以大大增加编译和链接时间。问题之一是每个包含声明模板的标头的文件都必须对其进行解析,检查其有效性,如果编译单元使用它,则生成的目标文件将包含代码,稍后将被删除链接器(如果被多个文件使用)。

      在我们的项目中,我们有一些大型模板,几乎包含在每个文件中,但其中只有两个实例化存在。我们通过使用显式实例化以及将模板代码分离到多个文件中大大缩短了编译时间。

      例如,这会给你:

      // MyClass.h
      template < typename T >
      class MyClass
      {
      void Print();
      T m_tValue;
      }
      
      // MyClass.inl
      #ifdef MY_CLASS_METHODS_ARE_NOT_INLINE
      #   define MY_CLASS_INLINE
      #else
      #   define MY_CLASS_INLINE inline
      #endif
      
      template < typename T >
      MY_CLASS_INLINE void MyClass< T >::Print()
      {
          std::cout << m_tValue << std::endl;
      }
      
      #undef MY_CLASS_INLINE
      
      // MyClass.cpp
      #include "MyClass.h"
      
      #define MY_CLASS_METHODS_ARE_NOT_INLINE
      #include "MyClass.inl"
      
      template class MyClass< int >;
      template void MyClass< int >::Print();
      
      #undef  MY_CLASS_METHODS_ARE_NOT_INLINE
      

      【讨论】:

        【解决方案4】:

        这完全取决于您的工具链(在这种情况下至少链接器和编译器,也许更多)。

        尝试一下,但请注意,即使更改工具链的单个部分,结果也可能会有很大差异。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-08-11
          • 2010-12-26
          • 1970-01-01
          • 1970-01-01
          • 2019-08-19
          • 2018-09-28
          • 2013-12-05
          相关资源
          最近更新 更多