迭代而不会产生IF语句的成本

时间:2010-10-08 23:53:02

标签: c++

我的问题是基于好奇心而不是是否有另一种解决问题的方法。这是一个奇怪/有趣的问题,所以请以开放的心态阅读。

让我们假设每个帧都有一个游戏循环。游戏循环依次通过无数if语句调用多个函数。例如,如果用户将GUI设置为false,则不刷新GUI,否则调用RefreshGui()。循环中还有许多其他if语句,如果它们是真的,它们会调用它们各自的函数。有些是if/if-else.../else,在最坏的情况下成本更高。如果if语句为真,则即使调用的函数也具有逻辑。如果用户想要对所有对象进行raypicking,请调用FunctionA(),如果用户想要点亮灯光,请调用FunctionB(),...,否则调用所有函数。希望你明白了。

我的观点是,这是多余的if语句。所以我决定使用函数指针。现在我的假设是函数指针总是比if语句更快。它是if / else的替代品。因此,如果用户想要在两种不同的相机模式之间切换,则他/她按下C键以在它们之间切换。键盘的回调函数将函数指针更改为正确的UpdateCamera函数(在这种情况下,函数指针可以指向UpdateCameraFps()UpdateCameraArcBall())...你得到了要点它的。

现在问题本身。如果我有几个具有相同签名的更新函数(假设为void (*Update)(float time)),那么函数指针可能指向其中任何一个。然后,我有一个用于存储指针的向量。然后在我的主更新循环中,我浏览向量并调用每个更新函数。我可以删除/添加甚至更改更新的顺序,而无需更改底层代码。在最好的情况下,我可能只调用一个更新函数,或者在最坏的情况下调用所有这些函数,所有这些都具有非常干净的while循环并且没有讨厌的(可能是嵌套的)if语句。我已经实现了这个部分,效果很好。我知道,随着while循环的每次迭代负责迭代向量,我正在检查是否itrBegin == itrEnd。更具体地说是while (itrBegin != itrEnd)。有没有办法避免调用if语句?我可以使用分支预测对我有利(或者我在不知情的情况下利用它)?

再次,请按原样提出问题,即我不是在寻找一种不同的方法(尽管非常欢迎您提供一种方法)。

  

编辑:一些回复表明这是一个不必要的过早优化,我不应该关注它,并且if语句的成本与所有单独更新函数中完成的工作相比是微不足道的。非常的,我完全同意,但这不是问题的关键,如果我没有让问题更清楚,我会道歉。我确实在所有回复中学到了很多新东西!

4 个答案:

答案 0 :(得分:6)

  

每个帧都有一个游戏循环

这是一种向后描述它的方式。游戏循环在帧期间不运行,帧在游戏循环体中处理。

  

我的假设是函数指针总是比if语句

更快

你测试过吗?它不太可能是真的,特别是如果你经常更改指针(这真的与CPU的分支预测混淆)。

  

我可以使用分支预测对我有利(或者我在不知情的情况下利用它)?

这只是一厢情愿的想法。通过在循环中调用一堆不同的函数进行间接调用,你肯定会对CPU分支预测逻辑起作用。

  

更具体地说是(itrBegin!= itrEnd)。有没有办法避免调用if语句?

在迭代函数链时,为了避免条件,你可以做的一件事是使用链表。然后每个函数都可以无条件地调用下一个函数,只需将终止逻辑安装为链中的最后一个函数(longjmp或其他)。或者你可能希望永远不会终止,在列表中包含glSwapBuffers(或图形API的等价物),然后将其链接回到开头。

答案 1 :(得分:4)

首先,分析您的代码。然后优化需要它的部件。

“如果”陈述是您最不关心的问题。通常,通过优化,您可以专注于循环,I / O操作,API调用(例如SQL),低效且经常使用的容器/算法。

使用函数指针尝试优化通常是您可以做的最糟糕的事情。你在代码可读性方面有机会,并且不利于CPU和编译器。我建议使用多态或只使用“if”语句。

答案 2 :(得分:1)

对我而言,这要求采用事件驱动的方法。而不是每次都检查是否需要做某事,而是监视传入的请求以执行某些操作。

我不知道你是否认为它偏离了你的方法,但它会将if ... then语句的数量减少到1。

while( active )
{
    // check message queue
    if( messages )
    {
        // act on each message and update flags accordingly
    }

    // draw based on flags (whether or not they changed is irrelevant)
}
编辑:我同意海报的说法,即循环不应该基于框架;帧应该基于循环。

答案 3 :(得分:0)

如果ifs检查的条件在循环期间没有改变,你可以检查它们一次,并在这种情况下设置一个函数指针指向你想要调用的函数。然后在循环中调用函数指针指向的函数。