Jar*_*edC 1 c++ performance templates
我有一个类是性能敏感代码路径的核心组件,所以我试图尽可能地优化它.该课曾经是:
class Widget
{
Widget(int n) : N(n) {}
.... member functions that use the constant value N ....
const int N; // just initialized, will never change
}
Run Code Online (Sandbox Code Playgroud)
构造函数的参数在编译时是已知的,因此我将此类更改为模板,以便可以将N编译为函数:
template<int N>
class Widget
{
.... member functions that use N ....
}
Run Code Online (Sandbox Code Playgroud)
我有一个方法的另一个类:
Widget & GetWidget(int index);
Run Code Online (Sandbox Code Playgroud)
但是,在模板化Widget之后,每个小部件都有不同的类型,因此我无法再定义这样的函数.我考虑了不同的继承选项,但我不确定模板的性能增益是否会超过继承函数调用的成本.
那么,我的问题是:
我很确定我想要两全其美(编译时/运行时),这可能是不可能的.但是,有没有办法在编译时获得知道N的性能,但是仍然可以将Widgets作为相同的类型返回?
谢谢!
这里的问题是,如果您将窗口小部件存储为相同的类型,那么从该存储中检索窗口小部件的代码(通过调用GetWidget)在编译时[*] 不知道N. 调用构造函数的代码知道N,但使用该对象的代码必须处理多种可能性.
由于性能命中(如果有的话)很可能出现在使用小部件的代码中,而不是创建它们的代码中,因此您无法避免在依赖于运行时信息的关键代码中执行某些操作.
这可能是在你的类模板实现的功能虚拟呼叫,是不是该使用N个不知道值的函数的非虚拟呼叫速度快:
class Widget {
public:
virtual ~Widget() {}
virtual void function() = 0;
};
template <int N>
class WidgetImpl : public Widget {
public:
virtual void function() { use N; }
};
Run Code Online (Sandbox Code Playgroud)
当N已知时,优化器可能会发挥最佳作用,因为它可以最佳地展开循环,转换算法等等.但是通过虚拟呼叫,你可以看到一个很大的缺点,即没有任何一个呼叫可以被内联(我猜想虚拟呼叫比没有内联时的非虚拟呼叫更不可能被预测) ).内联未知N的收益可能超过了解N的收益,或者可能更少.尝试他们两个,看看.
对于更为牵强的努力,如果有相当少的常见案例,您甚至可以通过实现关键小部件功能看到改进,例如:
switch(n) {
case 1: /* do something using 1 */; break;
case 2: /* do the same thing using 2 */; break;
default: /* do the same thing using n */; break;
};
Run Code Online (Sandbox Code Playgroud)
对所有情况"执行某些操作"但默认情况下可能是对常量上模板化的函数的调用,则默认值是与函数参数相同的代码而不是模板参数.或者它可以全部调用相同的函数(带有函数参数),但是在参数是常量的情况下依赖于编译器在优化之前内联调用,其结果与模板化的结果相同.
不是可以大规模维护的,并且通常不会像这样猜测优化器,但也许你知道常见的情况是什么,而编译器却没有.
[*]如果调用代码在编译时确实知道N的值,那么你可以GetWidget用这样的函数模板替换:
template <int N>
Widget<N> &getWidget(int index) {
return static_cast<Widget<N> &>(whatever you have already);
}
Run Code Online (Sandbox Code Playgroud)
但我认为来电者不知道,因为如果它确实那么你可能不会问...
| 归档时间: |
|
| 查看次数: |
284 次 |
| 最近记录: |