首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++:对抗多态开销

C++:对抗多态开销
EN

Stack Overflow用户
提问于 2010-11-06 02:24:22
回答 2查看 2.8K关注 0票数 8

我知道多态性会增加明显的开销。调用虚拟函数比调用非虚拟函数要慢.(我所有的经验都是关于GCC的,但我认为/听说对任何重新编译器来说都是如此。)

给定的虚拟函数多次在同一个对象上反复调用;我知道对象类型不会改变,大多数情况下编译器都可以很容易地推断出这一点:

代码语言:javascript
复制
BaseType &obj = ...;
while( looping )
    obj.f(); // BaseType::f is virtual

为了加快代码的速度,我可以这样重写上面的代码:

代码语言:javascript
复制
BaseType &obj = ...;
FinalType &fo = dynamic_cast< FinalType& >( obj );
while( looping )
    fo.f(); // FinalType::f is not virtual

我想知道在这些情况下,由于多态,避免这种开销的最佳方法是什么。

在我看来,上层转换(如第二段所示)的想法并不好:BaseType可能被许多类继承,而试图对所有类进行上传将是非常麻烦的。

另一个想法可能是将obj.f存储在函数指针中(没有测试这一点,也不确定它是否会杀死运行时开销),但是这个方法看起来并不完美:作为上面的方法,它需要编写更多的代码,并且无法利用一些优化(例如:如果FinalType::f是内联函数,它就不会内联-但我想避免这种情况的唯一方法是将其转换为其最终类型……)

有什么更好的方法吗?

编辑:,当然,这不会有太大的影响。这个问题主要是为了知道是否有什么可做的,因为看起来这种开销是免费的(这种开销看起来很容易消除)--我不明白为什么不这样做。

一个简单的关键字用于小的优化,比如C99 restrict,告诉编译器多态对象是固定类型的,这正是我所希望的。

不管怎么说,仅仅是回复评论,就会出现一些开销。看看这个特别的极端代码:

代码语言:javascript
复制
struct Base { virtual void f(){} };
struct Final : public Base { void f(){} };

int main( ) {
    Final final;
    Final &f = final;
    Base &b = f;

    for( int i = 0; i < 1024*1024*1024; ++ i )
#ifdef BASE
        b.f( );
#else
        f.f( );
#endif

    return 0;
}

编译和运行它,花费时间:

代码语言:javascript
复制
$ for OPT in {"",-O0,-O1,-O2,-O3,-Os}; do
    for DEF in {BASE,FINAL}; do
        g++ $OPT -D$DEF -o virt virt.cpp &&
        TIME="$DEF $OPT: %U" time ./virt;
    done;
  done           
BASE : 5.19                                                                                                                                                                         
FINAL : 4.21                                                                                                                                                                        
BASE -O0: 5.22                                                                                                                                                                      
FINAL -O0: 4.19                                                                                                                                                                     
BASE -O1: 3.55                                                                                                                                                                      
FINAL -O1: 1.53                                                                                                                                                                     
BASE -O2: 3.61                                                                                                                                                                      
FINAL -O2: 0.00                                                                                                                                                                     
BASE -O3: 3.58                                                                                                                                                                      
FINAL -O3: 0.00                                                                                                                                                                     
BASE -Os: 6.14                                                                                                                                                                      
FINAL -Os: 0.00

我想只有-O2,-O3和-Os在为Final::f做衬里。

这些测试已经在我的机器上运行,运行的是最新的GCC和Athlon(tm) 64 X2双核处理器4000+ CPU。我想在比较便宜的平台上会慢得多。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-11-06 02:37:34

如果动态调度是程序中的性能瓶颈,那么解决这个问题的方法就是不使用动态分派(不要使用虚拟函数)。

您可以使用模板和通用编程代替虚拟函数,用编译时多态性替换某些运行时多态性。这可能会或不会带来更好的性能;只有分析器才能肯定地告诉您。

但是要明确的是,正如wilhelmtell在对这个问题的评论中所指出的那样,动态调度所造成的开销很少足以让人担心。在用笨拙的自定义实现替换内置的方便之前,绝对要确保这是您的性能热点。

票数 8
EN

Stack Overflow用户

发布于 2010-11-06 14:28:07

如果您需要使用多态,那么使用它。没有比这更快的方法了。

不过,我会回答另一个问题:这是你最大的问题吗?如果是这样的话,您的代码已经是最优的或者几乎是最优的。如果不是,找出最大的问题是什么,然后集中精力于此。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4111563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档