10

我的 C++ 应用程序中有代码通常执行以下操作:

bool myFlag = false;
while (/*some finite condition unrelated to myFlag*/) {
    if (...) {
        // statements, unrelated to myFlag
    } else {
        // set myFlag to true, perhaps only if it was false before?
    }
}
if (myFlag) {
    // Do something...
}

我的问题与else我的代码声明有关。基本上,我的循环可能会根据不满足的某个条件将 myFlag 的值从 false 设置为 true。永远不会将标志从真设置为假。我想知道哪种语句在性能方面更有意义,也许由于编译器优化,这个问题实际上不是问题。

myFlag = true;

或者

if (!myFlag) myFlag = true;

我通常会选择前者,因为它需要编写更少的代码。但是,我开始怀疑它是否涉及对内存的不必要写入,因此如果 myFlag 已经为真,后者将阻止不必要的写入。但是,使用后者是否会因为有条件语句而需要更多时间,因此使用更多指令编译代码?

又或者是我想太多了……


更新 1

只是为了澄清一点......我后一种情况的目的是如果变量已经为真,则不写入内存。因此,仅当变量为假时才写入内存。

4

6 回答 6

13

几乎可以肯定,您最好只使用myFlag = true;.

您可以期望的最好的if (!myFlag) myFlag = true;结果是编译器会注意到if无关紧要并对其进行优化。特别是,该if语句需要读取的当前值myFlag。如果该值尚未在缓存中,则意味着指令将在等待从内存中读取数据时停止。

相比之下,如果您只是写入(无需先测试),则可以将值写入写入队列,然后可以立即执行更多指令。直到/除非您读取 myFlag 的值(并且假设它在写入后很快被读取,它可能仍会在缓存中,因此停滞将是最小的),您才会停止。

于 2013-02-22T22:05:42.970 回答
3

CPU 周期方面,更喜欢myFlag = true;考虑一下:即使编译器没有进行优化(不太可能),只需设置它需要一条asm语句,并通过if至少需要 1asm条语句。

所以就去接任务吧。

更重要的是,不要试图对这样低级的细节做出假设,具体的编译器优化完全违背直觉。

于 2013-02-22T22:05:20.780 回答
2

你知道支票没有实际意义吗?如果您盲目地将其设置为true并且未设置,则您正在设置它。如果它已经是true,则没有更改并且您没有 设置它,因此您可以有效地将其实现为:

myFlag = true;

关于潜在的优化,为了能够测试,值必须在缓存中,因此大部分成本已经支付。另一方面,分支(如果编译器不优化if离开,大多数都会)可能会对性能产生更大的影响。

于 2013-02-22T22:01:50.703 回答
0

正如其他人已经提到的那样,您很可能会过度思考这个问题,所以让我也这样做。如果您负担得起与myFlag. 事实上,你可以摆脱myFlag. 好的,我们开始:

while (/*some finite condition*/) {
    if (...) {
        // statements
    } else {
        while (/*some finite condition*/) {
            if (...) {
               // statements, repeated
            }
        }
        // Do something (as if myFlag was true in the OPs example)
        break;
    }
}

与所有性能优化一样:测量、测量、测量!

于 2013-02-22T22:41:11.417 回答
0

即使没有任何优化,是否if (!myFlag) myFlag = true;会比简单的执行时间更长,这是特定于架构的。myFlag = true;在某些体系结构(例如,https ://developer.qualcomm.com/hexagon-processor )中,两条语句都只需要一个周期即可执行。

在您的机器上计算的唯一方法是通过测量。

在任何情况下myFlag = true总是会更快或具有相同的执行时间if (!myFlag) myFlag = true;

于 2013-02-28T03:46:41.500 回答
0

这个问题也让我很头疼,所以我只是用以下代码(C#)自己测试了它:

        System.Diagnostics.Stopwatch time = new System.Diagnostics.Stopwatch();
        int i = 0;
        int j = 1;

        time.Start();
        if (i != 0)
            i = 0;
        time.Stop();
        Console.WriteLine("compare + set - {0} ticks", time.ElapsedTicks);

        time.Reset();
        time.Start();
        if (j != 0)
            j = 0;
        time.Stop();
        Console.WriteLine("compare - {0} ticks", time.ElapsedTicks);


        time.Reset();
        time.Start();
        i = 0;
        time.Stop();
        Console.WriteLine("set - {0} ticks", time.ElapsedTicks);

        Console.ReadLine();

结果:

比较 + 设置 - 1 个刻度

比较 - 1 个刻度

设置 - 0 滴答声

虽然用于设置值的时间肯定不为零,但它表明即使是单个查询也需要比设置变量更多的时间。

于 2013-11-21T17:07:50.730 回答