【问题标题】:Small repeated arithmetic vs creating new variables小重复算术与创建新变量
【发布时间】:2015-05-02 23:57:44
【问题描述】:

我正在用 C++ 编写低规格设备(~3MB RAM,~70MHz CPU),我想知道哪个运行效率更高(以及多少)。这是一段简化的代码,每秒运行 120-600 次:

void checkCollisions(int x, int y)
{
    int p1x = x, p1y = y+2;
    int p2x = x, p2y = y+3;
    int p3x = x+3, p3y = y+3;
    // And so on...

    if (wallAt(p1x-1, p1y) || wallAt(p2x-1, p2y))
        setCollision(LEFT, true);
    if (wallAt(p1x, p1y) || wallAt(p4x, p4y) || wallAt(p5x, p5y))
        inGround = true;
    else
        inGround = false;
    // And so on...
}

或者用它们的定义替换整数:

void checkCollisionsAlt(int x, int y)
{
    if (wallAt(x-1, y+2) || wallAt(x-1, y+3))
        setCollision(LEFT, true);
    if (wallAt(x, y+2) || wallAt(x+3, y) || wallAt(x+2, y))
        inGround = true;
    else
        inGround = false;
    // And so on...
}

这是示例的示意图:

第一个更容易理解,但我希望使用更多内存。它有多大的不同?

【问题讨论】:

  • 唯一可能的答案是:两者都编码,然后比较它们。
  • 关于比较代码,一种方法是编译(有和没有优化)汇编代码并进行比较。
  • 可以通过inGround = wallAt(p1x, p1y) || wallAt(p4x, p4y) || wallAt(p5x, p5y);来减少一些指令
  • 与在线征求意见相比,分析代码是了解代码执行情况的更好方法。
  • 我的投票是这无关紧要,因为优化编译器会将它们编译成相同的汇编代码。

标签: c++ performance algorithm memory memory-efficient


【解决方案1】:

需要思考的几点:

  1. 如果完整版也没有任何递归,您可以不用担心堆栈上的变量(p1x 等)。
  2. 堆栈消耗是短暂的,除非您有病态代码(例如每帧很重的深度递归),否则不会影响您。
  3. 在内存预算紧张的情况下,递归通常是个坏主意。
  4. 将它们作为显式命名的变量这一事实并不意味着它们在执行时会如此。
  5. 任何体面的编译器都可能识别变量的生命周期并将它们推送到寄存器。请使用您当前使用的编译器优化级别验证这一点,并在需要时考虑提高它。

另外,这些 p1x 等值的预期范围是多少。为什么不使用 short int?

堆栈内存增长的短暂性意味着您的峰值堆内存不会受到影响。堆栈可以增长和缩小,根据堆栈的布局和预算数量,您可能根本不必担心这一点。

注意:任何和所有堆分配都需要仔细审查。尝试实现自定义分配器,而不是产生标准的 malloc() 块开销。当然,您并没有提出问题,但是,请记住一件事。

【讨论】:

  • 整数的预期范围最大为 32768。经过一些修改,它可以很短。
【解决方案2】:

如果编译器按照您的意愿工作,那么将您的所有变量放入寄存器中将使您的代码更快的方法。我认为任何现代编译器都会从自身理解您的 2 个代码版本是相同的,并且会给出相同或非常相似的输出。它将尝试在两种情况下都使用核心寄存器,并且只有在没有足够数量的寄存器可用时才会使用内存——在这种情况下是堆栈。如果编译器为您提供保留中间汇编文件的选项,那么您可以深入了解您的代码和性能。请记住,低内存访问(使用寄存器代替)将提高您的代码性能。

【讨论】:

    【解决方案3】:

    如果机器以 70 MHz 运行,这意味着它每 600 秒有 117,000 个周期。

    如果每条指令平均需要 10 个周期,则它可以在 600 分之一秒内执行 11,700 条指令。

    当我查看您的代码时,无论是哪一个,我都猜测大约需要 100 条指令来执行它。 100/11,700 = 大约 1% 的时间用于运行此代码。

    您可以在汇编语言级别单步执行它,看看它需要多少指令,但可能不会有太大区别。

    我怀疑你在别处有更大的鱼要炸。

    【讨论】:

    • 还有近 100 个其他小情况略有相似,所以我认为最好改变我的编码方式,所以在编写这样的东西时,我会选择最好的一个。出于这个原因,尽管这个单独的场景没有占用大量的 CPU 时间,但这个问题仍然很重要。
    • @RandomPerson323:好的,那么让我给你一些带它去银行的,不能丢失的额外建议,你可以接受也可以不接受。这不是你提前做的事情。让代码运行,并使用this technique。它会准确地告诉您应该担心什么,而这几乎肯定是您现在所担心的以外的其他事情。
    猜你喜欢
    • 2014-07-04
    • 1970-01-01
    • 2016-10-19
    • 2018-10-28
    • 2014-05-05
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多