【问题标题】:Is it beneficial to make library functions templated to avoid compiler instructions?使库函数模板化以避免编译器指令是否有益?
【发布时间】:2019-04-10 12:09:39
【问题描述】:

假设我正在命名空间l 中创建自己的库。使尽可能多的命名空间成员模板化是否有益?这将鼓励编译器只为库用户实际调用的成员生成指令。为了说明我的观点,我将在这里进行演示:

1)

namespace l{
    template <typename = void>
    int f() { return 3; }
}

对比

2)

namespace l{
    int f() { return 3; }
}

没有在 main 中调用它来显示差异。

int main() { return EXIT_SUCCESS; }

函数1)不需要l::f()的额外说明:

main:
    push    rbp
    mov     rbp, rsp
    mov     dword ptr [rbp - 4], 0
    mov     eax, 0
    pop     rbp
    ret

函数 2) 确实需要针对 l::f() 的额外说明(如果再次调用 l::f()):

l::f()
    push    rbp
    mov     rbp, rsp
    mov     eax, 3
    pop     rbp
    ret
main:                                  
    push    rbp
    mov     rbp, rsp
    mov     dword ptr [rbp - 4], 0
    mov     eax, 0
    pop     rbp
    ret

【问题讨论】:

  • 如果目的是隐藏未“导出”的函数,请使用匿名命名空间。这将允许编译器在它们未被使用或到处内联时删除它们。
  • 你真的担心优化编译时间吗?或者是其他东西?如果您正在尝试(过早地)优化编译时间,是时候构建您担心的库或客户端代码了吗?

标签: c++ templates compilation


【解决方案1】:

tl;dr

将库函数模板化以避免编译器指令是否有益?

没有。发出死代码并不是编译的昂贵部分。文件访问、解析和优化(不一定按此顺序)需要时间,而且这种想法迫使库客户端读取和解析比常规标头 + 库模型更多的代码。

通常指责模板减慢构建,而不是加速构建。


这也意味着您无法提前构建库,因此每个用户都需要从头开始编译他们使用的任何部分,在每个翻译单元中使用它们。

编译所花费的总时间可能使用模板化版本会更长。您必须进行概要分析才能确定(我怀疑这个f 太小以至于无法衡量)但我很难将其视为有用的改进。

无论如何,您的比较并不具有代表性——一个好的编译器会在链接时丢弃死代码。有些还能够从静态库中内联代码,因此对编译时或运行时性能没有可靠的影响。

【讨论】:

  • 我基本同意。此外,它使事情变得不必要地臃肿。话虽如此,始终可以进行显式模板实例化,使库中所需的函数可用。但是,这违背了在这种特殊情况下使用模板的目的,因为据我了解,不生成代码是目标之一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 2013-08-22
  • 1970-01-01
  • 2013-10-23
相关资源
最近更新 更多