C++ 优化组合std::函数

C++ 优化组合std::函数,c++,optimization,functional-programming,c++11,mathematical-optimization,C++,Optimization,Functional Programming,C++11,Mathematical Optimization,是否可以优化一系列“粘合在一起”的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,因此必须在机器级别发现它 由于这是一种优化,需要时间,

是否可以优化一系列“粘合在一起”的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
将完美地表达我上面的意思):

一个“平凡”的编译器将使
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
可以使它(在数学上和其他任何意义上都是正确的!):

请注意,尽管我在这里谈论的是数学函数,但一般意义上的函数也可以进行类似的转换,但这需要更多的内省,这意味着开销


在设计数学和物理模拟时,我可以看到这一点非常重要,在这种情况下,将现有库函数合成为用户案例函数的通用性,以及所有常见的数学简化,可以成为一种表达能力强、性能高的计算软件的好方法。

编译器可以优化在特定允许的情况下,或者如果优化代码的行为“好像”是未经修改的代码


在这种情况下,不仅
x
y
为0会改变结果,而且如果
f
溢出,或者数据类型是浮点型或用户定义的,结果可能会因为这样的优化而改变。因此,我怀疑在实践中,您永远不会看到这种情况发生,并且必须(如果可能的话)在编译时编写一个组合函数(可能使用模板)。

编译器可以在特定允许的情况下进行优化,或者如果优化后的代码“好像”是未经修改的代码


在这种情况下,不仅
x
y
为0会改变结果,而且如果
f
溢出,或者数据类型是浮点型或用户定义的,结果可能会因为这样的优化而改变。因此,我怀疑在实践中,您永远不会看到这种情况发生,并且必须(如果可能的话)在编译时编写一个组合函数(可能使用模板).

这就是为什么您将优化留给编译器。它们在代数上是等价的,但由于FP不精确而不等价。您的两个版本的g将产生微妙的不同答案,如果在内部循环中调用,这可能非常重要-更不用说x,y,z为0时的行为差异了


其次,由于
函数的内容在运行时之前是未知的,因此编译器无法执行此类优化,因为它没有所需的数据。

这就是为什么您将优化留给编译器的原因。它们在代数上是等价的,但由于FP不精确,因此不等价。您的两个版本的g将d细微不同的答案,如果在内部循环中调用,这可能非常重要-更不用说如果x,y,z为0时的行为差异


其次,由于
函数
的内容在运行时之前是未知的,因此编译器无法执行此类优化,因为它没有所需的数据。

优化是标准允许的。标准中没有规定“不应优化”。(嗯,
volatile
有一些特别的注意事项,但不是针对您所询问的代码。)也许更多的问题是编译器是否能够安全地进行优化,以及是否值得编译器编写人员花时间寻找优化。我不认为这是标准所禁止的,因为这需要时间。但它可能是被禁止的,因为它改变了语义。对于x==0或y==0,未优化的版本给出NaN,优化后的将简单地返回0。我想这种优化可能与
constepr
函数有关。@duedl0r:是的,如果x、y和z是float或double类型,我希望g(0,0,0)计算0/0,从而返回NaN。我不明白它与
std::function
(和c++0x)有什么关系。您需要展示代码以使讨论变得有用。标准允许进行优化。标准中没有规定“您不应进行优化”。(好吧,关于
volatile
有一些特别的注意事项,但不是针对您所询问的代码。)也许更多的问题是编译器是否能够安全地进行优化,以及是否值得编译器编写人员花时间寻找优化。我不认为这是标准所禁止的,因为这需要时间。但它可能是被禁止的,因为它改变了语义。对于x==0或y==0,未优化的版本给出NaN,优化后的将简单地返回0。我想这种优化可以通过
constexpr
函数来实现。@duedl0r:是的,如果x、y和z是float或double类型,我希望g(0,0,0)计算0/0,从而返回NaN。我不明白它与
std:
double g(const double x, const double y, const double z){ return x*x*y*y*y*z*z*z*z/(x*y*y); }
double g( const double x, const double y, const double z){ return x*y*z*z*z*z; }