【发布时间】:2020-12-20 13:58:28
【问题描述】:
分配一个 lambda 是昂贵的。在 MSVC 上,我上次检查时它分配了 ~128 个字节。这使得在循环中创建 lambda 成为严重的性能问题。
在 Python 中,所有文字都被视为类似于constexpr,它们被计算(如果需要,类似于x = 10 * 25),然后在编译时缓存并在需要的地方简单地替换。
我想知道这是否是在 C++ 中完成的,因为像这样......
for (auto thing: things)
[](auto x){ /* do stuff */ }(thing);
...看起来它会多次分配 lambda 并且可以使用我上面描述的自动缓存。
那么,这是 C++ 中的性能问题吗?在 for 循环之前将 lambda 存储在一个变量中并使用该变量会更好吗?还是这样就可以了?
【问题讨论】:
-
这很可能是特定于实现的。但是,请注意,需要将没有捕获的 lambda 转换为函数指针。在引擎盖下,它只是一个正常的功能。很可能这就是这里会发生的事情。不过,您必须自己检查。
-
依赖于 C++ 中的上下文 lambda 的行为类似于匿名函数或函数对象。在您的奇怪示例中,它只是匿名函数,因此使用“AS IF 规则”编译器有权对此进行优化并删除 lambda(lambda 的主体将成为
for循环的一部分)。 -
编译器在局部变量分配方面通常非常聪明,即使是创建(但不存储)对象等动态内容也是如此。很有可能在循环中创建的对象将在函数进入时或在循环的第一次迭代中分配它们的内存。然后,该内存将被循环内“创建”的每个对象重用。您可以检查生成的汇编代码以确保此行为。
-
无关:python 中的
lambda是一个非常动态的对象,每次都会分配内存。 (它需要捕捉它的环境) -
首先:lambda 不捕获
thing,显然如果你捕获 128 个字节,那么 lambda 将占用 128+ 个字节。除了@Someprogrammerdude 所指出的,可以使用分析数据的编译器可以做得更好。他们可以检查是否实际的流模式,并查看是否在每个函数调用中都需要 lambda 分配(因此只需使堆栈帧更大)还是只是偶尔(相当于alloca。)。
标签: c++ performance memory-management lambda