首页 > 解决方案 > 在函数定义中有条件地执行计算的最佳方式

问题描述

    我有一个模拟,可以对大量步骤(大约 1e11)进行一组计算。然而,并非每次模拟都需要进行所有计算(尽管对于任何模拟,每一步都必须进行相同的计算)。由于模拟需要花费大量时间来运行,即使每个步骤的单个if语句也会对整体计算时间产生重大影响,因此我试图消除对if在每一步都进行相同评估的语句的需求。
    对于一小组计算,这可以通过简单地定义不同的函数并使用正确的计算组合来相当容易地完成,即

void justA() {
  // calculate A
}
void justB() {
  // calculate B
}
void both() {
  // calculate A
  // calculate B
}

并使用函数指针来预先确定使用哪个(就像在这个问题中一样)。但是对于更大的一组可能的计算,这变得不切实际。显然,这可以通过一系列if语句来解决,即

if (calculateA) {
  // calculate A
}
if (calculateB) {
  // calculate B
}
// ...
if (calculateZ) {
  // calculate Z
}

    但是对于 1e11 步模拟,这需要对每个计算进行 1e11 评估(所有这些都将评估为相同的结果)。

我的问题:有没有一种方法可以在没有 per-call 的情况下做到这一点if,它不需要为每种可能的计算组合硬编码不同的函数?


注意- 这必须在运行时完成,而不是使用 C++ 预处理器指令。

标签: c++optimization

解决方案


我假设您没有可能执行的 1e11 = 100,000,000,000(一千亿)个不同的操作。如果你这样做,那么我猜你有很多内存来存储程序。相反,我假设您可以按某种顺序执行多次的操作数量要少得多。

该顺序是如何确定的?解决方案将在很大程度上取决于此。

请注意,如果分支预测器成功预测了分支方向,则 an 的成本if实际上(基本上)为零。在实践中(尤其是在像你这样的场景中)它通常是正确的。问题是分支预测器查找表的大小。它不足以记住数百万个分支。但是,如果您可以将分支减少到一个很小的数量 - 也许通过有一个外部循环迭代函数指针数组的元素并依次调用每个 - 您可以依靠分支预测器每次都正确(分支将始终导致循环的开始,除了最后一次)。

在真正的硬件上,昂贵的部分不是if,而是分支,以及大多数其他控制流结构,例如do/while并且for还涉及分支。


推荐阅读