lambda在GCC中的运行速度有多快

dcn*_*dcn 27 c++ performance benchmarking lambda c++11

在G ++ 中用C++ 0x Lambda Expression玩弄了一下,我想知道在不使用lambda函数的情况下,与一般/特定情况相比,性能有多好.

有没有人知道一个或多或少全面的关于lambda表达性能的讨论或者在开发过程中应该避免使用它们的情况?

Arm*_*yan 28

如果你考虑用老派的方式来定义一个结构operator ()作为另一种方式,那么就没有任何区别,因为lambdas几乎与之相当.语法上更方便.让我们等一个更完整的答案......

  • 这几乎是*完整的答案. (8认同)

Eli*_*lay 16

当第一次遇到lambda表达式时,很多人都会产生模糊的印象,即创建这些函数时会发生一些运行时编译魔术.具体来说,如果你有一个函数返回一个新生成的函数作为结果,看起来每次调用周围函数时都会"创建"返回的函数.但这是错误的 - 一个lambda表达式(在任何语言中都是如此)包含一些可以像任何其他代码一样编译的代码,并且它们都是静态发生的,不需要为运行时留下任何成本.

唯一的问题是关闭的变量会发生什么,但这并不排除这种编译 - 创建一个闭包,你只需将闭包数据(这些变量)与一个指向静态编译代码的指针配对.这在性能方面的含义是,根本不应该有性能损失 - 封闭变量.即使有封闭的变量也没有成本 - 任何其他方法来解决你所遇到的任何问题都需要以某种方式打包这些值,所以分配的成本是相同的,无论你如何保持它(明确地,或者隐含在封闭的变量中).如果替代解决方案不需要打包某些值,那么也不需要使用闭包来关闭它们.这与执行代码所需的本地分配非常相似 - 无论代码是来自具有本地范围的闭包还是来自需要相同类型的本地状态的其他范围,这显然都是相同的.

同样,这是所有带闭包的语言中的东西,并且C++代码没有理由遇到其他语言没有的性能问题.C++ lambda表达式中的一个奇怪之处是需要指定您关闭的变量,而在大多数其他语言中,您只需将所有内容都默认关闭.这看起来似乎给了C++代码一些优势,可以更好地控制需要与闭包一起打包的东西 - 但这对于编译器来说很容易自动完成,没有明确的注释.它导致函数式语言编译器最常见​​的事情之一 - "lambda提升" - 将函数有效地提升到顶层,避免在运行时创建闭包(如果不需要).例如,如果你写(使用一些类似JS的伪代码):

function foo(x) {
  return function(y) { return y+3; }
}
Run Code Online (Sandbox Code Playgroud)

然后很容易(对于编译器和人类)看到返回的函数不依赖x,并且编译器现在可以解除它,就像你写道:

function generated_name1234(y) { return y+3; }
function foo(x) {
  return generated_name1234;
}
Run Code Online (Sandbox Code Playgroud)

当仅关闭某些值时,使用类似的技术.

但这是分歧.底线是lambda表达式不会导致一些性能损失 - 闭合变量与否.

(至于将lambda表达式与using进行比较operator(),我不确定大多数C++编译器会做什么,但lambdas应该更快,因为没有任何方法调用所需的运行时调度.即使lambdas是作为匿名类实现的,也是如此()运算符,上述技术也适用于这种情况,这意味着可以编译调度机制,这意味着它不应该有额外的成本,使其类似于匿名类对于高效编译点.)

  • 在C++中,没有运行时调度任何未声明为`virtual`的成员函数,根据我的经验,_extremely_很少声明`operator()``virtual`.重点是,lambdas很少会比手写的仿函数更快(但从不慢). (2认同)

lur*_*her 5

我没有看到任何设计理由为什么闭包应该是较小的表演者而不是具有相同数量和传递参数大小的等效函数

甚至闭包捕获所有上下文变量应该能够优化掉lambda中实际使用的上下文变量.

特定的上下文变量(通过值或通过引用捕获)将需要在实例化时初始化的一些存储,这发生在执行期间首次找到lambda的点.但是这个存储不需要堆,堆栈分配完全没问题.

lambda 与常规函数完全相同,唯一的区别完全是sintactical; 它在其他函数中定义,并且可以捕获一些外部变量,这些变量被编译为附加的上下文参数.context参数可能在定义lambda的位置具有类似POD的初始化.

如果一个特定的编译器(即:g ++或clang)与上面的行为发生冲突,它就是一个糟糕实现的警告信号.clang能够轻松扩展设计所传递的优化,因此从长远来看,任何这样的缺点都应该更容易解决,相比之下,g ++

底线是如果你不使用上下文变量,lambda(应该)与常规自由函数完全无法区分到编译器