Lambda函数在GCC中的运行速度有多快?

| 我在G ++中使用C ++ 0x Lambda表达式进行了一些摸索之后,我想知道与不使用lambda函数的替代方法相比,在一般/特定情况下的性能如何。 是否有人对lambda表达性能或在开发时会感到更舒适的情况下仍应避免使用lambda表达性能的情况有所了解?     
已邀请:
        如果您考虑用老式的方法来定义带有with0的结构作为替代方法,则不会有任何区别,因为lambda与之相当。只是语法上更方便。让我们等待更完整的答案...     
        第一次遇到lambda表达式时,许多人模糊地印象是创建这些函数时发生了一些运行时编译魔术。具体地说,如果您有一个函数返回一个新创建的函数作为其结果,则似乎在每次调用周围的函数时都“创建了”返回的函数。但这是错误的-lambda表达式(在任何语言中都是如此)包含一些可以像其他任何代码一样进行编译的代码,并且它们都是静态发生的,而运行时无需付出任何代价。 唯一的问题是被封闭的变量会发生什么,但这并不排除编译的可能性,要创建一个封闭,只需将封闭数据(这些变量)与指向静态编译代码的指针配对即可。就性能而言,这意味着根本不应该有性能损失-是否存在封闭变量。即使存在封闭变量,也没有成本-解决问题的任何其他方法都需要以某种方式打包这些值,因此,分配成本是相同的,无论您如何保留它(明确地说,或隐式封闭变量)。如果替代解决方案不需要打包某些值,那么也就不需要使用闭包对其进行封闭。这实际上与执行代码所需的本地分配相同-无论代码是来自具有本地范围的闭包还是来自需要相同本地状态的其他范围,这显然都是相同的。 同样,这是所有具有闭包语言的东西,并且C ++代码没有理由遇到其他语言没有的性能问题。在C ++ lambda表达式中,一个奇怪的事情是需要指定要关闭的变量,而在大多数其他语言中,默认情况下您只是关闭了所有内容。这似乎为C ++代码提供了一些优势,可以更好地控制需要使用闭包包装的东西-但这对于编译器而言,无需显式注释即可自动完成,这非常容易。这导致函数语言的编译器执行最常见的操作之一-\“ lambda lift \”-将功能有效地提升到顶层,从而避免了在不需要时在运行时创建闭包的需求。例如,如果您编写(使用一些类似于JS的伪代码):
function foo(x) {
  return function(y) { return y+3; }
}
那么很容易(对于编译器和人类)都可以看到返回的函数不依赖于
x
,并且编译器现在可以将其提升,就像您写的那样:
function generated_name1234(y) { return y+3; }
function foo(x) {
  return generated_name1234;
}
当仅关闭某些值时,使用类似的技术。 但这是分歧的。最重要的是,lambda表达式不会导致性能下降(无论是否为封闭变量)。 (关于将lambda表达式与使用ѭ4I进行比较,我不确定大多数C ++编译器会做什么,但是lambdas应该更快,因为任何方法调用都不需要运行时分派。即使lambdas被实现为匿名类也是如此。如果使用
()
运算符,上述技术也可以在这种情况下应用,这意味着可以将调度机制编译掉,这也就意味着它也不必增加成本,这类似于匿名类的特殊情况对于高效编译而言是微不足道的。)     
我没有看到任何设计原因,为什么闭包的性能要比传递参数的数量和大小相同的等效函数低 即使捕获所有上下文变量的闭包也应该只能优化lambda中实际使用的上下文变量。 特定的上下文变量(通过值或通过引用捕获)将需要在实例化时初始化一些存储,这在执行过程中首次发现lambda时发生。但是此存储不必是堆,堆栈分配完全可以。 lambda与常规函数完全相同,唯一的区别是完全在语法上;它在其他函数中定义,并且可以捕获一些外部变量,这些变量被编译为附加的上下文参数。上下文参数在定义lambda的点可能具有类似于POD的初始化。 如果特定的编译器(即g ++或clang)的行为与上述行为发生冲突,则表示实施不正确的警告信号。 clang具有轻松扩展通过设计传递的优化的能力,因此与g ++相比,从长远来看,应该更容易解决任何此类缺点 最重要的是,如果您不使用上下文变量,则lambda与(应该)与常规的自由函数和编译器完全没有区别     
        就像其他人提到的那样,没有理由解释由lambda导致的编译器生成的闭包与手写的闭包在性能上应该没有任何不同。为了验证这一点,我只是用手写类更改了解析器中使用的lambda。它们都只包含几行严格的代码,并执行了数百万次,因此性能的每一次更改都将立即引起注意。结果-执行时间完全相同。因此,不存在性能差异。     
        在某些情况下(游戏环境),我们开始避免使用lambda,因为创建的闭包(如果具有捕获的值)具有关联的new / delete以保存任何捕获的值。尽管在许多环境中这不是问题,但我们要一次节省微秒的时间,以获得最佳性能。 Lambda(带有封闭变量的变量)在我们的配置文件中占有重要地位,并且是最早使用的Lambda。     

要回复问题请先登录注册