在链接时定义的C常量

时间:2012-03-17 21:06:03

标签: c performance constants

我有一个非常对性能敏感的应用程序,并且好奇我是否可以保存一些常量来进行链接。我使用了许多全局常量(例如,模拟尺寸),这些常量使用的是疯狂的数量。我尝试将它们从常量更改为变量,性能急剧下降。因此,我创建了一个有点复杂的系统,它从配置文件中分配常量,并为请求的参数集显式构建可执行文件。因此,我想尽量减少每次参数更改时重建的内容。

问题是我是否可以预编译一些对象,并在链接时输入值。 我能想到的最可能的实现是将这些常量作为const参数包含在需要它们的函数中,并希望编译器/链接器优化产生的结果与将它们硬编码为{{{ 1}}常数。关于如何使这项工作的任何建议?

(你知道人们怎么说“但这不重要,除非你在集群上的科学计算中做了数十亿次吗?” - 我是那个在科学计算中做数十亿次的人在集群上。是的,我还会在完全实现之前对任何事情进行基准测试。)

3 个答案:

答案 0 :(得分:4)

假设gcc,您可以使用外部链接声明常量,将它们放入自己的源文件中,并使用link-time optimizations进行编译和链接。

在clang的情况下,我推荐一种类似的方法,但不是使用常规LTO,而是使用-emit-llvm -c编译为bitcode,并且只在链接时编译为本机代码作为最后一步。

此外,您可以按原样保留代码(即使用预处理程序定义)并信任ccache以避免不必要的重新编译。

答案 1 :(得分:3)

你必须分析变量减速的原因,最好通过查看生成的汇编程序,通常是编译器选项-S

如果你有常量,加速可能有很多原因:

  • 小整数常量可以直接用于装配操作
  • 编译器可以进行循环展开
  • 如果常数是2
  • 的幂,则可能存在特殊的算术技巧

另一方面,如果只将指针传递给函数const,并且编译器无法排除您的const限定对象的别名,则可能会减速。 const仅表示您无权更改值,但编译器无法知道它是否意外更改。这里用restrict声明指针可能会有所帮助。

因此,找出问题点,在汇编程序中将它们与两个不同的版本(常量和const限定变量)进行比较,并尝试找出减速的​​原因。

使用inline来彻底优化故障点。

如果没有别的帮助,如果你碰巧很好地本地化,你甚至可以考虑用文字常量编写一个产生该函数的脚本,并在每次运行之前编译一小段代码。如果您的运行时间很长,那么短期编译和重新链接可能会有所回报。

答案 2 :(得分:2)

你可以,但它并没有真正帮助你。使用不同常量重新编译所获得的收益是因为编译器在编译时知道值并且可以基于此进行优化。如果您构建一个对象并在以后将其与常量数据相关联,则与使用变量相同,您将受到性能影响。

听起来像一个有趣的问题,这些天真正毛茸茸的男人优化的机会并不多:)