【问题标题】:Code is significantly slower even though it should not [closed]即使代码不应该[关闭],代码也明显变慢
【发布时间】:2017-08-09 04:42:54
【问题描述】:

总结:我们的软件使用了一个实用函数,这个函数被调用了百万次,所以我们必须对其进行优化。我注意到,通过对这个实用函数中的代码进行简单的调整,执行速度要快得多,从 10 秒的执行时间缩短到 0.6 秒。这是实用函数中的调整:

从code1(10秒内完成):

double d = (a * x3 + b * y3 + c) / l;
if (std::abs(d) > inMaxDToL) return false;

d = (a * x4 + b * y4 + c) / l;
if (std::abs(d) > inMaxDToL) return false;

return false;

到代码 2(0.6 秒内完成):

double d = (a * x3 + b * y3 + c) / l;
if (std::abs(d) > inMaxDToL) return false;

return false;

我所做的是在代码 2 中早些时候返回 false。显然在第一个代码中,就工作量而言,第 1 + 2 行等同于第 3 + 4 行。所以我想知道为什么删除第 3 + 4 行可以大大加快处理速度?

另一个将执行时间从 10 秒减少到 0.6 秒的调整是替换 incall 函数调用:

if (!inBetween(x1, y1, x2, y2, x3, y3)) return false;

及其内容:

if ((x2 - x1) * (x2 - x3) > epsilon) return false;
if ((y2 - y1) * (y2 - y3) > epsilon) return false;

代码也从 10 秒加速到 0.6 毫秒。

我正在使用 Visual Studio 2013 及其编译器。

我错过了什么吗?

编辑:使其更清晰:

  1. 那几行只是实用函数的一部分
  2. 出于调试目的,我故意返回 false

【问题讨论】:

  • 似乎两者都可以优化到仅return false;,因为没有副作用并且所有情况都以false结束。
  • 不能说 Visual Studio,但在 Linux 上,您可以生成具有某种操作类型的 SIMD 指令。
  • 是 a) 第一个条件几乎总是正确 b) x4, y4 在缓存中冷吗?
  • 对不起,我不清楚:1. 运行百万次时的 10s 和 0.6s 2. 那几行只是实用功能的一部分 3. 我故意返回 false 用于调试目的
  • 如果您发布了整个实用程序函数,您会得到一个更好的答案,因为您正在计时。

标签: c++ optimization time


【解决方案1】:

this post 写得非常好,我很确定你是分支预测失败的受害者。

另外,将第二次操作的结果放在另一个变量中可能是值得的。如果您不打算返回 'd',写入不同的变量可能会让编译器进行更多优化。

【讨论】:

  • 太棒了,谢谢@AlexG!
【解决方案2】:

您可以利用惰性求值(短路布尔求值)并在单个条件下进行两次检查,避免将结果分配给变量

// second condition will only evaluate if the first one is false.
if((std::abs((a * x3 + b * y3 + c) / l) > inMaxDToL) || 
   (std::abs((a * x4 + b * y4 + c) / l) > inMaxDToL))
   return false;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    相关资源
    最近更新 更多