【问题标题】:Checking a conditional vs setting a variable multiple times; low-level optimization多次检查条件与设置变量;低级优化
【发布时间】:2016-07-24 02:05:35
【问题描述】:

如果我正在搜索一组值并为每个值运行代码,并且我想在找到某种质量时打开一个布尔值,然后在我为该对象运行代码时再次退出,运行条件检查是否需要关闭布尔值是否更快,或者在每个循环中简单地关闭它是否更快?

例如(伪代码):

bool found = false;
for(particle in literallyAHaystack) {
    bool isNeedle = particle == "needle";

    if(isNeedle) {
        found = true;
    }

    // [some code that uses the 'found' variable]

    if(isNeedle) {
        found = false;
    }
}

bool found = false;
for(particle in literallyAHaystack) {
    bool isNeedle = particle == "needle";

    if(isNeedle) {
        found = true;
    }

    // [some code that uses the 'found' variable]

    found = false; // a conditional no longer surrounds this statement
}

我知道这是非常低级且通常毫无意义的优化,但我仍然对它的真相感兴趣。我希望不要因为这个琐碎的问题而冒犯任何人。

【问题讨论】:

  • 那么,呃...为什么你同时拥有isNeedlefound?它们似乎是多余的。
  • @user2357112:我认为这个想法是想象found 可能由if 中的某些内容设置,因此将整个内容编写为嵌套的if() 子句而不使用布尔值来记录结果以前的检查需要重复代码。

标签: c optimization micro-optimization


【解决方案1】:

如果bool found 是一个局部变量,那么在几乎所有CPU 架构上,几乎可以肯定,在每种情况下,无条件地将其设置为false 会更好。如果它完全存在于编译器输出中(而不仅仅是变成分支逻辑的一部分),它可能只会在寄存器中。写寄存器是最便宜的操作之一,比分支便宜得多。

即使它曾经命中内存,回写缓存也很常见,因此重复存储到同一位置只会命中 L1,而不会产生流向更大的共享缓存或主内存的流量。


如果编译器在每个循环结束时发出的代码实际上将标志存储在内存中,则在下一次迭代中检查标志将导致约 5 个周期的存储转发延迟(例如在 Intel Haswell 上)。

但如果出现问题,那是编译器没有很好地优化代码的错。这就是我们使用编译器而不是直接在 asm 中编写的原因:编译器可能会完全优化掉 found 变量。这很好,并且不是重组你的 C 的论据。

有关 x86 上此类内容的更多信息,请参阅 http://agner.org/optimize/ 标签 wiki 中的其他链接。

要查看您的代码如何编译,请将其放在 http://gcc.godbolt.org/ 上(并使用 O3 -march=haswell -ffast-math 或其他东西。)


如果found 是全局的(并且可能已被另一个线程最后修改),那么仅先读取它可能是有意义的,因此运行您的代码的核心不需要使其他核心的缓存副本无效行。

我正在想象一个标志,它是不同线程可能使用的共享状态结构(由受锁保护的关键部分中的代码使用)的一部分。 (不过,在这种情况下,这将是一个糟糕的设计,因为found 在使用后总是留下false,所以没有持久状态,所以它应该是本地的。)

不过,为了避免存储,可能不值得使用条件分支。如果在任何循环迭代中都修改了标志(即如果针曾经匹配),那么您也可以随意修改它。

只有当你可以从一些商店到同一个位置到零而不是更少时,避开商店才最有用。缓存工作。

例如向量化时,如果您想写入向量的 3 个元素而不是全部 4 个元素,则有时对目标进行重叠存储很有用,并且可以写入超出存储内容的末尾。例如在this code

【讨论】:

  • 非常感谢。我知道示例代码没有完全的意义,但你准确地回答了这个问题。
【解决方案2】:

第二个会“更快”,因为没有条件检查,因此不需要跳转。

会明显更快吗?几乎绝对不是。无论如何,编译器可能已经进行了这种优化,尽管不要引用我的话——我不确定它是否这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 2017-02-22
    相关资源
    最近更新 更多