Lambda 捕获与参数 - 任何性能差异?
Posted
技术标签:
【中文标题】Lambda 捕获与参数 - 任何性能差异?【英文标题】:Lambda captures vs parameters - any performance difference? 【发布时间】:2021-11-19 04:06:27 【问题描述】:auto lambdaFunction1 = [](someClass& obj, int x)/**/;
auto lambdaFunction2 = [&someClassObj, x]()/**/;
使用捕获变量或将它们作为参数传递的 lambda 是否会有任何性能差异?如果我处于可以使用任何东西的位置,我是否应该总是更喜欢其中一个选项而不是其他选项?有什么规则吗?还是只是喜欢谁的问题?
PS:我知道在同样的情况下我将没有这样的选择,例如使用 stl 算法,我问的是我可以同时使用这两种算法的情况
【问题讨论】:
唯一的判断方法是分析一个优化的构建,看看是否存在性能差异。优化器非常聪明。 【参考方案1】:粗略的回答:
您是否在某个时候将 lambda 转换为对象(如 std::function
)?
如果不是,并且每个 lambda 使用都是通过模板,很可能它都是内联的,这并不重要。大多数采用 lambda 参数的 STL 都是这样工作的,而且速度非常快。在这种情况下,请使用将来更容易阅读和理解的内容。
如果您确实将其转换为函数对象,那么使用常规函数指针而不是 std::function
会更便宜,因为函数本身没有动态分配的捕获对象。
更准确的答案:基准测试!
【讨论】:
为了清楚起见,您不能使用带有捕获 lambda 的常规函数指针 @PaulSanders 没错。函数点只是指向某段代码的指针。std::function
有两个指针:一个指向代码的指针,以及一个类型擦除指针,指向保存捕获变量的内部结构。当然,具体实施可能会有所不同。【参考方案2】:
捕获和参数本质上是不同的,优化方式也不同。
让我们看看你的 lambdas:
struct lambdaFunction1_type
auto operator()(someClass& obj, int x) const /* ... */
lambrdaFunction1;
struct lambdaFunction2_type
someClass& obj;
auto operator()(int x) const /* ... */
lambdaFunction2someClassObj;
如您所见,捕获的行为类似于类数据成员,而参数的行为类似于……嗯,一个参数。两者都有不同的用途。
两者还使用不同的内联过程。与往常一样,当使用诸如std::function
之类的多态包装器时,编译器优化的效果要差得多。如果没有堆省略,编译器可能不会优化动态分配的大小,因此它可能会影响优化的可能性。
如果我处于可以使用任何东西的位置,我是否应该总是更喜欢其中一个选项而不是其他选项?有什么规定吗?
我想说总是选择对你来说最清楚的东西。如果您对性能、度量、基准和配置文件有疑虑。
你也可以去检查一些代码生成的程序集。
【讨论】:
以上是关于Lambda 捕获与参数 - 任何性能差异?的主要内容,如果未能解决你的问题,请参考以下文章
如何在标准函数 lambda c++ 11 中正确捕获参数包
VS2010 中的 C++ 嵌套 lambda 错误,带有 lambda 参数捕获?