提问者:小点点

使用一个循环还是两个循环


我正在读这个博客:-https://developerinsider.co/why-is-one-loop-so-Much-slower-than-two-loops/。我决定使用C++和Xcode来检验它。所以,我写了一个简单的程序,下面给出,当我执行它时,我对结果感到惊讶。实际上,第二个函数比第一个函数慢,这与文章中所说的相反。有谁能帮我弄清楚为什么会这样吗?

#include <iostream>
#include <vector>
#include <chrono>
    
using namespace std::chrono;
    
void function1() {
    const int n=100000;
            
    int a1[n], b1[n], c1[n], d1[n];
            
    for(int j=0;j<n;j++){
        a1[j] = 0;
        b1[j] = 0;
        c1[j] = 0;
        d1[j] = 0;
    }
            
    auto start = high_resolution_clock::now();
        
    for(int j=0;j<n;j++){
        a1[j] += b1[j];
        c1[j] += d1[j];
    }
            
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
        
    std::cout << duration.count() << " Microseconds." << std::endl;  
}
    
void function2() {
    const int n=100000;
            
    int a1[n], b1[n], c1[n], d1[n];
            
    for(int j=0; j<n; j++){
        a1[j] = 0;
        b1[j] = 0;
        c1[j] = 0;
        d1[j] = 0;
    }
            
    auto start = high_resolution_clock::now();
            
    for(int j=0; j<n; j++){
        a1[j] += b1[j];
    }
    
    for(int j=0;j<n;j++){
        c1[j] += d1[j];
    }
            
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
        
    std::cout << duration.count() << " Microseconds." << std::endl;
}
        
int main(int argc, const char * argv[]) {
    function1();
    function2();
    
    return 0;
}

共2个答案

匿名用户

第二个函数的迭代次数是第一个函数的两倍,这意味着条件分支的两倍(这在现代CPU上仍然相当昂贵),这反过来导致它变得更慢。而且,第二个函数必须分配一个额外的迭代器变量,并且它必须将一个迭代器变量递增两倍。

您的代码和本文中演示的代码之间还有一个主要区别:您的代码在堆栈上分配数组,而本文的代码在堆上分配数组。这对数组在性能方面的表现有严重的性能影响。

文章还提到,对于不同系统和不同大小的数组,行为可能不是统一的。他的文章专门围绕磁盘缓存的含义展开,这些含义在代码中可能有效,也可能不有效。

匿名用户

在您的情况下,第二个函数更快的原因(我不认为这在任何机器上都能工作)是因为在点处有更好的cpu缓存,您的cpu有足够的缓存来存储数组,您的操作系统需要的东西等等,第二个函数可能会比第一个慢得多。从性能的角度来看。如果有足够多的其他程序运行,我怀疑这两个循环代码会给出更好的性能,因为第二个函数的效率明显不如第一个函数,如果有足够多的其他东西缓存,性能领先抛出缓存将被消除。