我的问题是出于好奇,而不是是否有其他方法可以解决这个问题。这是一个奇怪/有趣的问题,所以请以开放的心态阅读它。
让我们假设有一个游戏循环每帧都被调用。游戏循环依次通过无数的 if
语句调用多个函数。例如,如果用户将 GUI 设置为 false,则不要刷新 GUI,否则调用 RefreshGui()
。循环中还有许多其他 if
语句,如果它们为真,它们将调用各自的函数。有些是 if/if-else.../else
,在最坏的情况下成本更高。即使被调用的函数,如果 if
语句为真,也有逻辑。如果用户想要对所有对象进行光线拾取调用 FunctionA()
,如果用户想要对灯光进行光线拾取,则调用 FunctionB(), ...,否则调用所有函数。希望你明白了。
我的意思是,那是很多多余的 if 语句。所以我决定改用函数指针。现在我的假设是函数指针总是比 if
语句快。它是 if/else 的替代品。因此,如果用户想要在两种不同的相机模式之间切换,他/她可以按 C
键在它们之间切换。键盘的回调函数将函数指针更改为正确的 UpdateCamera
函数(在这种情况下,函数指针可以指向 UpdateCameraFps()
或 UpdateCameraArcBall( )
)...你明白了它的要点。
现在回到问题本身。如果我有几个更新函数都具有相同的签名(假设为 void (*Update)(float time)
),那么函数指针可能会指向其中的任何一个。然后,我有一个用于存储指针的 vector 。然后在我的主更新循环中,我遍历 vector 并调用每个更新函数。我可以删除/添加甚至更改更新的顺序,而无需更改底层代码。在最好的情况下,我可能只调用一个更新函数,或者在最坏的情况下调用所有更新函数,所有这些都带有一个非常干净的 while 循环并且没有讨厌的(可能嵌套的)if 语句。我已经实现了这部分并且效果很好。我知道,对于负责遍历 vector 的 while 循环的每次迭代,我都在检查 itrBegin == itrEnd
。更具体地说,while (itrBegin != itrEnd)
。有什么办法可以避免调用 if 语句吗?我可以使用分支预测来发挥我的优势吗(或者我是否已经在不知不觉中利用了它)?
再次强调,请按原样回答这个问题,即我不是在寻找不同的方法(尽管我们非常欢迎您提供一种方法)。
EDIT: A few replies state that this is an unneeded premature optimization and I should not be focusing on it and that the if-statement(s) cost is minuscule compared to the work done in all the separate update functions. Very true, and I completely agree, but that was not the point of the question and I apologize if I did not make the question clearer. I did learn quite a few new things with all the replies though!
最佳答案
there is a game loop that is being called every frame
这是一种倒退的描述方式。游戏循环不在帧期间运行,帧在游戏循环的主体中处理。
my assumption is that a function pointer is always going to be faster than an if statement
你测试过吗?这不太可能是真的,尤其是当您频繁更改指针时(这确实会扰乱 CPU 的分支预测)。
Can I use branch prediction to my advantage (or am I taking advantage of it already without knowing)?
这只是一厢情愿。通过在循环中进行一个间接调用来调用一堆不同的函数,您肯定会违反 CPU 分支预测逻辑。
More specifically while (itrBegin != itrEnd). Is there any way to avoid the call to the if statements?
为了在迭代函数链时避免条件语句,您可以做的一件事是使用链表。然后每个函数都可以无条件地调用下一个函数,您只需将终止逻辑安装为链中的最后一个函数(longjmp 或其他)。或者您可以希望永远不会终止,在列表中包含 glSwapBuffers
(或您的图形 API 的等效项)并将其链接回开头。
关于c++ - 迭代而不产生 IF 语句的成本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3895048/