首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当“虚拟者”是相当大的开销时,有什么经验法则吗?

当“虚拟者”是相当大的开销时,有什么经验法则吗?
EN

Stack Overflow用户
提问于 2013-07-08 17:06:32
回答 4查看 369关注 0票数 7

我的问题基本上是在标题中完全阐述的,但让我详细说明一下。

问题:可能值得重新措辞,virtual方法必须有多复杂/简单,才能使该机制成为相当大的开销?这有什么经验法则吗?例如,如果花费10分钟,使用I/O、复杂的if语句、内存操作等,这不是一个问题。或者,如果您编写virtual get_r() { return sqrt( x*x + y*y); };并在循环中调用它,您将遇到麻烦。

我希望这个问题不要太笼统,因为我寻求一些一般性但具体的技术答案。要么很难/不可能知道,要么虚拟调用需要如此多的时间/周期资源,而数学则需要这个I/O。

也许有些技术人员知道一些通用的数字进行比较或做一些分析,并能分享一般的结论。令人难堪的是,我不知道如何做那些花哨的asm分析=/。

我还想给出一些背后的理由,以及我的用例。

我想我见过很多人为了表现而不使用像森林中的射击这样的虚拟设备的问题,就像很多人问他们:“你确定虚拟开销真的是你的问题吗?”

我相信,在我最近的工作中,我遇到了一个可以放在河两岸的问题。

还请记住,我不问如何改进接口的实现。我相信我知道怎么做。我是想知道什么时候该做,或者选择正确的球棒。

用例:

我做了一些模拟。我有一个类,基本上提供了一个运行环境。有一个基类和多个派生类,它们定义了一些不同的工作流。基本收集东西作为共同的逻辑和分配I/O源和汇。衍生工具定义特定的工作流,或多或少是通过实现RunEnv::run()。我认为这是一个有效的设计。现在,让我们想象一下,作为工作流主体的对象可以放在2D或3D平面上。在这两种情况下,工作流都是通用的/可互换的,因此我们正在处理的对象可以具有公共接口,尽管使用的方法非常简单,比如Object::get_r()。除此之外,还可以为环境定义一些stat记录器。

最初,我想提供一些代码片段,但最终得到了5个类和2-4个方法,即code的墙。我可以根据要求把它贴出来,但是它会把这个问题延长到目前大小的两倍。

关键点是:RunEnv::run()是主循环。通常很长(5分钟-5小时)。它提供了基本的时间检测,调用RunEnv::process_iteration()RunEnv::log_stats()。都是虚拟的。理由是。我可以派生RunEnv,例如针对不同的停止条件重新设计run()。我可以重新设计process_iteration(),例如,如果我必须处理一个对象池,以各种方式处理它们,就可以使用多线程。另外,不同的工作流需要记录不同的状态。RunEnv::log_stats()只是一个调用,它将已经计算出的有趣的统计数据输出到std::ostream中。我猜使用的是虚拟的,并没有真正的影响。

现在,假设迭代通过计算对象到原点的距离来工作。所以我们有接口double Obj::get_r();Obj是为二维和三维案例实现的。在这两种情况下,getter都是一个简单的2-3乘法和加法的数学.

我还在不同的内存处理中进行了实验。例如,有时坐标数据存储在私有变量中,有时存储在共享池中,因此即使是get_x()也可以通过实现get_x(){return x;};get_x(){ return pool[my_num*dim+x_offset]; };来虚拟。想象一下用get_r(){ sqrt(get_x()*get_x() + get_y()*get_y()) ;};计算一些东西。我怀疑这里的虚拟会扼杀表演。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-07-08 17:12:07

在C++中对x86的虚拟方法调用产生类似于(单个继承)的代码:

代码语言:javascript
复制
    mov ecx,[esp+4]
    mov eax,[ecx]       // pointer to vtable
    jmp [eax]           

如果没有虚拟,与非虚拟成员函数相比,您将节省一条mov指令。因此,在单一继承的情况下,性能的影响可以忽略不计。

如果您有多个继承,或者更糟的是,虚拟继承,则虚拟调用可能要复杂得多。但这更多的是类、层次结构和体系结构的问题。

经验法则:

如果方法的主体比单个mov指令慢很多倍(>100倍),那么只需使用virtual,就不用麻烦了。否则-分析您的瓶颈,和优化。

更新:

对于多个/虚拟继承案例,请查看此页面:http://www.lrdev.com/lr/c/virtual.html

票数 8
EN

Stack Overflow用户

发布于 2013-07-08 17:16:19

这有什么经验法则吗?

对于像这样的问题,最好的,最普遍的经验法则是:

在优化之前测量代码

试图使您的代码在不进行度量的情况下表现良好,这是一条通向不必要的复杂代码的确定路径,而这些代码在所有错误的地方都进行了优化。

所以,在有确凿的证据证明virtual是问题之前,不要担心虚拟函数的开销。如果您有这样的证据,那么您可以在这种情况下删除virtual。但是,更有可能的是,您会发现,找到加速计算的方法,或者避免在不需要计算的地方进行计算,将带来更大的性能改进。但再说一遍,不要只是猜测--先测量一下。

票数 8
EN

Stack Overflow用户

发布于 2013-07-08 17:24:04

首先,当然,任何差异都将取决于编译器、体系结构等。在某些机器上,虚拟调用和非虚拟调用之间的差异很难测量,至少在另一个机器上,它将(或将--我对这台机器的经验相当古老)彻底清除管道(不对间接跳转进行分支预测)。

在大多数处理器上,虚拟函数的实际成本是内联能力的丧失,从而导致其他优化可能性的丧失。换句话说,成本实际上将取决于调用函数的上下文。

然而,更重要的是:虚拟函数和非虚拟函数有不同的语义.所以你不能选择:如果你需要虚拟语义,你必须使用虚拟;如果你不需要虚拟语义,你就不能使用虚拟语义。所以这个问题真的没有提出来。

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

https://stackoverflow.com/questions/17532226

复制
相关文章

相似问题

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