g++编译C++17时Lambda函数慢于独立函数的优化问题咨询
C++17下Lambda与独立函数的性能差异疑问
类似问题此前已有相关讨论:一类讨论聚焦C++11中Lambda函数的开销,但测试结果存在偶然性;另一类对比的是Lambda与自定义函数对象的性能差异,未直接涉及Lambda和普通独立函数的优化程度对比。
本人使用g编译器、遵循C17标准,针对简单曼哈顿距离计算场景做了性能测试,分别采用Lambda表达式、独立函数两种实现逻辑,经多组输入重复测试后发现,Lambda版本的运行时间系统性高出约3%,完整测试代码如下:
#include <vector> #include <iostream> #include <chrono> using namespace std; template < class result_t = std::chrono::milliseconds, class clock_t = std::chrono::steady_clock, class duration_t = std::chrono::milliseconds> auto since(std::chrono::time_point<clock_t, duration_t> const& start) { return std::chrono::duration_cast<result_t>(clock_t::now() - start); } int manhattanDistance(int x1, int y1, int x2, int y2) { return abs(x1 - x2) + abs(y1 - y2); } int fWithoutLambda(int x, int y, vector<vector<int>>& points) { int min_d = numeric_limits<int>::max(); int idx = -1; for (int i = 0; i < points.size(); i++) { auto d = manhattanDistance(x, y, points[i][0], points[i][1]); if ((x == points[i][0] || y == points[i][1]) && d < min_d) { idx = i; min_d = d; } } return idx; } int fWithLambda(int x, int y, vector<vector<int>>& points) { auto manh = [x, y](int x2, int y2) {return abs(x - x2) + abs(y - y2);}; int min_d = numeric_limits<int>::max(); int idx = -1; for (int i = 0; i < points.size(); i++) { auto d = manh(points[i][0], points[i][1]); if ((x == points[i][0] || y == points[i][1]) && d < min_d) { idx = i; min_d = d; } } return idx; } int main() { size_t repeats = 10; int time_no_lambda{0}; int time_lambda{0}; for (size_t j = 0; j < repeats; ++j) { int n = 1000000; vector<vector<int>> v(n); int counter = 0; for (auto& el : v) { v[counter++] = {counter, counter%10}; } int x = 10, y = 5; auto start = std::chrono::steady_clock::now(); fWithLambda(x, y, v); auto tim_0 = since(start).count(); time_lambda += tim_0; fWithoutLambda(x, y, v); time_no_lambda += (since(start).count() - tim_0); } std::cout << "Elapsed(ms), lambda =" << (time_no_lambda/repeats) << std::endl; std::cout << "Elapsed(ms), no lambda =" << (time_lambda/repeats) << std::endl; }
请问是否存在编译器对独立函数调用做了优化、但未对Lambda表达式执行同等程度优化的可能性?
问题解答
不存在编译器偏向优化独立函数、刻意不对Lambda做同等优化的情况,你观测到的3%系统性性能差,来自测试方法缺陷和代码细节问题,和Lambda本身的固有开销无关:
- 测试顺序引入的固定偏差:你的每轮测试都先执行Lambda版本、再执行非Lambda版本。第一次执行时,测试数据刚写入内存,L1/L2/L3缓存未命中率高,且CPU尚未完成睿频拉升到稳定最高性能状态,本身就会比后执行的逻辑慢。把两个函数的执行顺序随机打乱、或者先跑几轮预热再正式计时,这个固定差值会直接消失。
- 代码缺失头文件干扰优化:你的代码中使用了
numeric_limits<int>::max(),却没有包含<limits>头文件,部分g++版本下会触发隐式声明兼容逻辑,可能影响编译器的内联、常量传播优化决策。 - 从语义层面说,捕获两个int变量的Lambda本质是编译器自动生成的、带两个int成员的函数对象,其
operator()是隐式inline的,和普通独立函数没有任何本质区别。开-O2及以上优化等级时,只要代码写法等价,编译器对两者能做的内联、循环展开、常量折叠优化程度完全一致,生成的汇编指令几乎没有差别。如果是无优化(-O0)编译,Lambda因为是类成员函数,调用栈处理逻辑和全局独立函数有细微差异,会表现出少量性能差,但无优化编译的性能数据没有实际参考价值,正式发布的生产程序不会使用该编译等级。
如果要做可靠的微基准性能测试,建议拆分独立的预热阶段和正式计时阶段,随机打乱不同实现的执行顺序,同时固定CPU运行频率、关闭睿频和系统地址空间随机化,排除软硬件环境的干扰。
内容的提问来源于stack exchange,提问作者A. Fenzry
相关产品推荐
相关产品推荐

