是否可以优化一系列“粘合”std::function
和/或是否有任何尝试执行此操作的实现?
我的意思是最容易以数学方式表达:说我想制作一个函数函数std::function
:
f(x,y,z) = x^2 * y^3 * z^4
g(x,y,z) = f(x,y,z) / (x*y^2)
是否有一种方法可以让STL /编译器实现者优化掉算术部分是调用g
的函数对象,是从f
的函数对象创建的?
这将是函数的一种符号简化,但因为它是std::function
,所以必须在机器级别上发现它。
由于这是一种优化,需要时间,而且可能不是免费的(在时钟周期和/或内存中),标准可能不允许这样做?它倾向于非常接近通常通过VM运行的语言。 (我认为LLVM不仅仅是Java,还有运行时优化)。
编辑:为了使讨论“更有用”,这里是一个简短的代码片段(我理解lambda不是std::function
,但lambda可以存储在std::function
中,所以假设auto
以下std::function<T>
表示T
,auto f = [](const double x, const double y, const double z){ return x*x*y*y*y*z*z*z*z; };
auto g = [](const double c, const double y, const double z){ return f(x,y,z)/(x*y*y); };
将完全表达我的意思:
g
“普通”编译器会使double g(const double x, const double y, const double z){ return x*x*y*y*y*z*z*z*z/(x*y*y); }
等同于
std::function
虽然优化的double g( const double x, const double y, const double z){ return x*y*z*z*z*z; }
可以实现(数学上和其他方面都是正确的!):
{{1}}
请注意,虽然我在这里谈论的是数学函数,但是对于一般意义上的函数可以进行类似的转换,但这需要更多的内省,这意味着开销。
在设计数学和物理模拟时,我可以看到这一点非常重要,其中将现有库函数合成到用户案例函数中的一般性,通过所有常用的数学简化,可以提供一种表达性但性能良好的计算软件的好方法
答案 0 :(得分:4)
这就是您将优化留给编译器的原因。由于FP不精确,它们在代数上是等价的但不等价。你的两个版本的g会产生微妙的不同答案,如果在内循环中调用,这可能非常重要 - 更不用说x,y,z为0时的行为差异。
其次,由于function
的内容在运行时是未知的,因此编译器无法执行此类优化,因为它没有所需的数据。
答案 1 :(得分:1)
允许编译器在特定允许的情况下进行优化,或者如果优化代码表现为“好像”它是未经过优化的代码。
在这种情况下,x
或y
不仅会更改结果,但如果f
溢出,或者数据类型为浮点或用户定义,则结果可能会更改为这种优化的结果。因此,我怀疑在实践中你永远不会看到它发生,并且必须(如果可能的话)在编译时组合一个组合函数(大概是使用模板)。