C++11性能:Lambda内联与函数模板专业化
C++11 Performance: Lambda inlining vs Function template specialization
我的问题是对此进行扩展:为什么编译器可以比普通函数更好地优化lambda?
重申一下,结论是lambda创建了不同的专门化,编译器可以简单地内联这些专门化,而函数指针则不那么容易内联,因为一组函数原型只有一个专门化。考虑到这一点,函数指针模板会像/更快的lambdas一样快吗?
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
template <class F>
int operate(int a, int b, F func)
{
return func(a, b);
}
template <int func(int, int)>
int operateFuncTemplate(int a, int b)
{
return func(a, b);
}
int main()
{
// hard to inline (can't determine statically if operate's f is add or sub since its just a function pointer)
auto addWithFuncP = operate(1, 2, add);
auto subWithFuncP = operate(1, 2, sub);
// easy to inline (lambdas are unique so 2 specializations made, each easy to inline)
auto addWithLamda = operate(1, 2, [](int a, int b) { return a + b; });
auto subWithLamda = operate(1, 2, [](int a, int b) { return a - b; });
// also easy to inline? specialization means there are 2 made, instead of just 1 function definition with indirection?
auto addWithFuncT = operateFuncTemplate<add>(1, 2);
auto subWithFuncT = operateFuncTemplate<sub>(1, 2);
}
因此,如果我能根据性能对这些进行排名,那么:
operatorFuncTemplate
>=operate<LAMBDA>
>=operate<FUNCTIONPTR>
在一些不平凡的例子中,这种关系可能会失败吗?
如果编译器可以跟踪"此函数指针指向此函数",则编译器可以通过函数指针内联调用。
有时编译器可以做到这一点。有时他们做不到。
除非将lambda存储在函数指针std::function
或类似的类型擦除包装中,否则调用lambda的编译器知道lambda的类型,也知道lambda主体。编译器可以简单地内联函数调用。
使用函数模板不会改变这一点,除非参数是constexpr
,就像函数非类型模板参数:
template <int func(int, int)>
这就是一个例子。在这里,函数主体中的函数模板保证在编译时是已知的。
然而,将func
传递到其他任何地方,编译器可能会失去对它的跟踪
在任何情况下,任何速度差异都将高度依赖于上下文。有时,lambda的内联导致的较大二进制大小会导致比无法内联函数指针更大的速度减慢,因此性能可能会相反。
任何像你试图提出的普遍主张有时都是错误的。
相关文章:
- 函数模板部分专业化-有什么解决方法吗
- 我应该声明我的函数模板专业化还是定义它们就足够了
- std::转换move构造函数的模板专业化的变体
- 纯虚函数的模板专业化
- 为什么这不是函数模板的部分专业化
- 在允许的函数模板的明确专业化中扣除了多个模板参数
- C - 具有非类型模板参数的模板类上的专业化函数模板
- C++11性能:Lambda内联与函数模板专业化
- 为什么不允许对成员函数的模板专业化
- 成员函数模板参数的部分专业化
- 对于需要其他模板参数的类型函数的部分模板专业化
- 实例化错误后成员函数模板的专业化,以及成员函数的顺序
- 函数模板专业化语法
- 具有模板化函数的专业化模板类
- 稍后添加模板函数的专业化
- 模板专业化-成员函数
- 为什么类中不允许函数模板专业化
- c++函数模板专业化
- c++函数模板专业化
- 函数模板专业化和Abrahams/Dimov示例