c++ - 迭代而不产生 IF 语句的成本

标签 c++

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

让我们假设有一个游戏循环每帧都被调用。游戏循环依次通过无数的 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/

相关文章:

c++ - 不知道如何将 "JOHN"更改为 "John"

c++ - C++ 中的 std::variant cout

c++ - 我可以从一组较小的文件构建 CMakeLists.txt 吗(以提高 CMakeLists.txt 的可读性和可维护性)

c++ - HEAP_NO_SERIALIZE 堆中的多线程访问

c++ - 处理非常大的多语言项目

c++ - 将 if else 与 switch 一起使用

c++ - Boost spirit解析器如何打印符号表匹配的变量?

c++ - 你能不先分配资源就把数据复制到 `char*`指针吗?

c++ - std::function 的问题

c++ - std::vector保留并调整NUMA位置的大小