我目前的代码看起来像
while (very_long_loop) {
...
y1 = getSomeValue();
...
x1 = y1*cos(PI/2);
x2 = y2*cos(SOME_CONSTANT);
...
outputValues(x1, x2, ...);
}
显而易见的优化是提前计算余弦。我可以通过使用值填充数组来完成此操作,但我想知道是否可以让编译器在编译时计算它们?
编辑:我知道C没有编译时评估,但我希望用宏来做一些奇怪而丑陋的方法。
答案 0 :(得分:6)
如果你很幸运,你将不必做任何事情:现代编译器对同一翻译单元和内在函数(最有可能包括数学函数)的函数进行常量传播。
查看程序集以检查编译器是否属于这种情况,并在必要时提高优化级别。
答案 1 :(得分:1)
不。预先计算的查找表将是唯一的方法。实际上,Cosine
(和Sine
)甚至可能在您的库中以这种方式实现。
首先配置文件,稍后优化。
答案 2 :(得分:1)
不,不幸的是。
我建议编写一个小程序(或脚本)来生成这些值的列表(然后可以#include
到正确的位置),这是作为构建过程的一部分运行的。
顺便说一下: cos(pi / 2)= 0!
答案 3 :(得分:1)
您认为计算cos
比访问更昂贵。也许你的架构不是这样。因此,您应该进行一些测试(分析) - 与优化思路一样。
答案 4 :(得分:0)
不是预先计算这些值,而是可以使用全局变量来保存值,这些值将在程序启动时计算一次。
答案 5 :(得分:0)
不,C没有函数的编译时评估的概念,如果它们是double类型,则不具有符号常量。将它们作为立即操作数的唯一方法是预先计算它们,然后在宏中定义它们。例如,这是C库为pi执行的方式。
答案 6 :(得分:0)
如果检查代码并且编译器没有从循环中提取常量值,那么自己这样做。
如果trig函数的参数在示例代码中是常量,那么要么自己预先计算它们,要么使它们成为静态变量,这样它们只计算一次。如果它们在调用之间变化,但在循环内是恒定的,则将它们移动到循环外部。如果它们在循环的迭代之间变化,则查找表可能更快,但如果这是可接受的准确度,那么实现自己的触发功能以更低的精度停止计算也是一种选择。
答案 7 :(得分:0)
我对Christoph上面的答案感到敬畏。
因此在这种情况下不需要做任何事情,其中gcc对数学函数有一些了解。但是如果你有一个函数(可能由你实现),你的C编译器无法计算或者你的C编译器不那么聪明(或者你需要填充复杂的数据结构或其他原因),你可以使用一些更高级的语言充当宏处理器。在过去,我使用eRuby就是为了这个目的,但是(ePerl也应该很好用,并且是另一种显而易见的,或多或少舒适的选择。
您可以指定make规则,用于将扩展名为.eruby
(或.eperl
或其他)的文件转换为剥离了该扩展名的文件,例如,如果您编写文件module.c.eruby
或module.h.eruby
然后make
会自动知道如何分别生成module.c
或module.h
,并使其保持最新状态。在您的make规则中,您可以轻松添加一些注释,直接警告编辑文件。
如果您使用的是Windows或类似的东西,那么我就无法解释如何添加对您喜欢的IDE自动为您运行此转换的支持。但我相信它应该是可能的,或者只要您需要更改make
(或其他)文件,就可以在IDE外部运行.eruby
。
顺便说一句,我已经看到,通过使用Lua作为宏语言实现的eLua实现了非常小的代码行。当然,支持正则表达式和灵活布局规则的任何其他脚本语言也应该起作用(但是由于严格的空格规则,Python因此而被用于此目的。)