小重复算术与创建新变量

时间:2015-05-02 23:57:44

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

我正在用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...
}

以下是示例图表:

Example Diagram

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

3 个答案:

答案 0 :(得分:1)

要考虑几点:

  1. 如果完整版本也没有任何递归,你可以更少担心堆栈中的变量(p1x等)。
  2. 堆栈消耗是短暂的,除非你有病态代码,否则不应该打击你,例如每个帧都很重的深度递归。
  3. 在内存预算紧张的情况下,递归通常是一个坏主意。
  4. 你将它们作为明确命名的变量这一事实并不意味着它们在执行时会如此。
  5. 任何体面的编译器都可能识别变量的生命周期并将它们推送到寄存器。请使用您当前使用的编译器优化级别对此进行验证,并在需要时考虑将其更改。
  6. 此外,p1x等的这些值的预期范围是什么?为什么不使用short int?

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

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

当我查看你的代码时,我估计大约有100条指令要执行它。 100 / 11,700 =大约1%的时间用于运行此代码。

您可以在汇编语言级别单步执行它以查看它需要多少指令,但它可能不会产生太大的影响。

我怀疑你有更大的鱼可以在其他地方煎炸。