问题描述
编译器是否可以内联 lambda 函数以提高效率,就像使用简单的标准函数一样?
例如
std::vectorvd;std::for_each(vd.begin(), vd.end(), [](const double d) {return d*d;});
或者是没有优化导致效率下降?
第二个问题:我在哪里可以检查我使用的编译器是否优化了内联函数的调用,这些调用被发送到算法?我的意思是,如果一个函数——而不是函数对象——被发送到一个算法,最后一个得到一个指向该函数的指针,一些编译器优化指向内联函数的指针,而另一些则没有.
在简单的情况下,比如你的例子,你应该期望 lambdas 比函数指针有更好的性能,见
为什么编译器可以比普通函数更好地优化 lambda?
正如其他人已经指出的那样,不能保证您的调用会被内联,但您有更好的机会使用 lambda.检查调用是否已内联的一种方法是检查生成的代码.如果您使用 gcc,请将 -S 标志传递给编译器.当然,前提是你能看懂汇编代码.
2018 年 9 月 11 日更新:Vipul Kumar 指出了两个编译器标志在他的编辑中.
GCC -Winline
><块引用>
如果声明为 inline 的函数无法内联,则发出警告.即使使用此选项,编译器也不会警告系统标头中声明的内联函数失败.
编译器使用各种启发式方法来确定是否内联函数.例如,编译器会考虑被内联的函数的大小以及当前函数中已经完成的内联量.因此,源程序中看似微不足道的更改可能会导致-Winline 产生的警告出现或消失.
据我所知,如果您的函数未声明为内联,则此编译器标志很可能没有有帮助.尽管如此,知道它存在还是很好的,它部分回答了您的第二个问题.
他指出的另一个标志是:
Clang -Rpass=inline
><块引用>
发送优化报告的选项
优化报告在高层次上跟踪所有主要决策由编译器转换完成.例如,当内联决定将函数 foo() 内联到 bar() [...]
我自己没有使用过这个,但根据文档,它可能对您的用例有用.
每当生成的程序集很重要时,我都会亲自检查它.
Can/does the compiler inline lambda functions to increase efficiency, as it might with simple standard functions?
e.g.
std::vector<double> vd;
std::for_each(vd.begin(), vd.end(), [](const double d) {return d*d;});
Or is there loss of efficiency caused by lack of optimisation?
A second question: where I can check if the compiler I use has optimised calls of inline functions, which are sent to an algorithm? What I mean is, if a function—not a function object—is sent to an algorithm, the last one gets a pointer to the function, and some compilers optimize pointers to inline functions and others don't.
In simple cases, like your example, you should expect better performance with lambdas than with function pointers, see
Why can lambdas be better optimized by the compiler than plain functions?
As others have already pointed out, there is no guarantee that your call will be inlined but you have better chances with lambdas. One way of checking whether the call has been inlined is to check the generated code. If you are using gcc, pass the -S flag to the compiler. Of course, it assumes that you can understand the assembly code.
Update on Sep 11, 2018: Vipul Kumar pointed out two compiler flags in his edit.
GCC -Winline
Warn if a function that is declared as inline cannot be inlined. Even with this option, the compiler does not warn about failures to inline functions declared in system headers.
The compiler uses a variety of heuristics to determine whether or not to inline a function. For example, the compiler takes into account the size of the function being inlined and the amount of inlining that has already been done in the current function. Therefore, seemingly insignificant changes in the source program can cause the warnings produced by -Winline to appear or disappear.
As I understand this, if your function is not declared inline, this compiler flag is most likely not helpful. Nevertheless it is good to know it exists and it partly answers your second question.
The other flag that he pointed out is:
Clang -Rpass=inline
Options to Emit Optimization Reports
Optimization reports trace, at a high-level, all the major decisions done by compiler transformations. For instance, when the inliner decides to inline function foo() into bar() [...]
I haven't used this one myself but based on the documentation it might be useful for your use case.
I personally check the generated assembly whenever it is that important.
这篇关于lambda 是否像 C++ 中的函数一样内联?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!