c++ 虚函数机制 效率问题
2011-04-21 11:39 Rollen Holt 阅读(2283) 评论(0) 编辑 收藏 举报原文:http://blog.csdn.net/metalkittie/archive/2008/11/12/3281916.aspx
今天在c++坛子里瞎逛,看到精华坛里在讨论“为什么虚函数效率低”的问题,
××楼主回答面试官说“跟cpu流水线执行效率有关”
××某人回答“因为虚函数需要一次间接的寻址... 而一般的函数可以在编译时定位到函数的地址,虚函数(动态类型调用)是要根据某个指针定位到函数的地址. ”
×ד虚函数有个虚函数表,而且会传一个index索引~!会间接寻址!”
×ד流水线执行的话,和"命中率"有关吧. 也就是说在流水线后端,已经译码成功的,和正在执行的代码的后继是一样的. 否则流水线会中断,也就是说在后端做的是无效的,需要重新译码.”
搞笑的是以下人的回复:
×ד的确,计算机程序效率说到底和计算机指令流水线息息相关(还和缓存命中率有关)。但是,把虚函数效率低的原因解释到流水线这一层,是极其变态的,这个考官很可能是在卖弄自己的水平而已。”
×ד楼主以后你要是遇到这种考官,你和他谈与非逻辑门,硅锗原子的组成和爱因斯坦相对论对虚函数的影响,绝对震惊四座!”
×ד说是因为流水线执行的原因,根本与问题不着边际。或者应该说影响流水线执行是效率低的无数原因中的一种才好。”
×ד首先是由this指向查找虚函数表,然后找到相应的虚函数地址
比非虚函数多查找一次
如果是(多继承)基类指针指向派生类对象的话,有可能会涉及this指针的调整
比如先访问基类的成员数据再访问派生类的析构函数 就要进行一次this指针的调整
具体可以参见 insied the c++ object model的多重继承下的virtual functions ”
×ד一些C++的书籍有明确的说明,针对类的虚函数的机制,如果有虚函数的话,编译器会为类增加一个虚函数表(VBL),当在动态执行程序时,会到该虚函数表中寻找函数。多增加了一个过程,效率肯定会低一些,但带来了运行时的多态。”
×ד流水线 貌似说的是 CPU执行代码的提前取指令吧
虚函数 效率低 是因为 执行过程中会跳转两次(首先找到对象的函数表,其次通过该函数表中存的虚函数表地址找到真正的执行地址),这样CPU运行的时候会跳转两次,而普通函数只跳一次。CPU每跳转一次,预取指令基本上就要作废很多,所以效率会很低。”
/////////////////////////////////////最后得分者
和流水线相关是说得通的,究其原因还是因为存在动态跳转,这会导致分支预测失败,流水线排空。
设想一下,如果说不是虚函数,那么在编译时期,其相对地址是确定的,编译器可以直接生成jmp/invoke指令;
如果是虚函数,多出来的一次查找vtable所带来的开销,倒是次要的,关键在于,这个函数地址是动态的,譬如
取到的地址在eax里,则在call eax之后的那些已经被预取进入流水线的所有指令都将失效。流水线越长,一次分支预测失败的代价也就越大。
pf->test();
011E146D mov eax,dword ptr [pf]
011E1470 mov edx,dword ptr [eax]
011E1472 mov esi,esp
011E1474 mov ecx,dword ptr [pf]
011E1477 mov eax,dword ptr [edx]
011E1479 call eax <------------------------- 分支预测失效
011E147B cmp esi,esp
011E147D call @ILT+355(__RTC_CheckEsp) (11E1168h)
此兄接着回答道“说到流水线,penalty基本上都是因为气泡(也就是分支指令造成预取失效),知道这个以后碰到了就不会再卡壳了。虽然引入流水线(流水线其实是 RISC最初使用的),极大提高了效率,流水线不是越长越好。像P4,几十级流水线,频率虽高,但是性能不好,很大原因就是因为流水线实在臭长。有兴趣可 以去看看CPU怎么做分支预测,乱序执行的。”
//////////////////////////////////
还是贴上原帖的地址吧 http://topic.csdn.net/u/20081031/12/06d0e218-8aab-4203-850c-9e6b76099c09.html
由此还引申出一个问题 虚函数在编译器里是怎么工作的
==============================================================================
本博客已经废弃,不在维护。新博客地址:http://wenchao.ren
我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他
们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其
实我是一个程序员
==============================================================================