【问题标题】:An additional conditional statement is making a program faster另一个条件语句使程序更快
【发布时间】:2012-11-19 17:59:27
【问题描述】:

阅读Why is it faster to process a sorted array than an unsorted array? 后,我在主循环中添加了一个额外的测试。看来这个额外的测试正在使程序更快。

int main()
{
    // Generate data
    const unsigned arraySize = 32768;
    int data[arraySize];

    for (unsigned c = 0; c < arraySize; ++c)
         data[c] = std::rand() % 256;

    //Don't sort the array
    //std::sort(data, data + arraySize);

    // Test
    clock_t start = clock();
    long long sum = 0;

    for (unsigned i = 0; i < 100000; ++i)
    {
        // Primary loop
        for (unsigned c = 0; c < arraySize; ++c)
        {
            if (data[c] >= 128)
                sum += data[c];

            //With this additional test, execution becomes faster
            if (data[c] < 128)
                sum += data[c];
        }
    }

    double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;

    std::cout << elapsedTime << std::endl;
    std::cout << "sum = " << sum << std::endl;
}

我得到大约 4.2 秒的附加测试和 18 秒没有附加测试。 额外的测试不应该让程序变慢而不是让它变快吗?

【问题讨论】:

    标签: c++ performance branch-prediction


    【解决方案1】:

    由于那个特别额外的测试,这个等价的代码:

    for (unsigned i = 0; i < 100000; ++i)
    {
        // Primary loop
        for (unsigned c = 0; c < arraySize; ++c)
        {
           if (data[c] >= 128)
                sum += data[c];
    
            //With this additional test, execution becomes faster
            if (data[c] < 128)
                sum += data[c];
         }
    }
    

    变成这样:

    for (unsigned i = 0; i < 100000; ++i)
    {
      // Primary loop
      for (unsigned c = 0; c < arraySize; ++c)
      {
        sum += data[c];//because exactly one condition is guaranteed to be
                       //true in each iteration (in your code)!
                       //the equivalent is as if there is no condition at all!
      }
    }
    

    这就是它变得更快的原因。

    这是因为 unusual 附加测试和 相同 主体,编译器能够优化代码,删除 if 条件。当你有一个if 时,编译器就无法做到这一点。

    试着写这个:

    sum -= data[c]; //the body is not identical anymore!
    

    if 条件之一。我确信编译器将能够优化代码。它现在应该发出较慢的机器代码。


    请注意,外部循环可以完全省略,尽管它不太依赖于额外的测试::

    // Primary loop
    for (unsigned c = 0; c < arraySize; ++c)
    {
        sum += 100000 * data[c];
    }
    

    或者,这个:

    // Primary loop
    for (unsigned c = 0; c < arraySize; ++c)
    {
        sum += data[c];
    } 
    sum = 100000 * sum; //multiple once!
    

    【讨论】:

    • 值得注意的是,由于上下文的变化,它的编译器优化。通常,这不会发生,并且附加条件会减慢执行速度。
    • 外循环只是为了测量运行时间,我想说
    • @icepack,“通常”是什么意思。编译器优化不正常吗?
    • @Sancho 编译器优化正常。但是这种特殊的优化是不寻常的,因为它在实践中很少见,编译器需要认识到这两个测试都是完全一致的,并且主体是相同的。
    • @Sancho,是的,这很正常,但通常你不会有包含 2 个条件的代码,而不是没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多