我正在读这个博客:-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; }
第二个函数的迭代次数是第一个函数的两倍,这意味着条件分支的两倍(这在现代CPU上仍然相当昂贵),这反过来导致它变得更慢。而且,第二个函数必须分配一个额外的迭代器变量,并且它必须将一个迭代器变量递增两倍。
您的代码和本文中演示的代码之间还有一个主要区别:您的代码在堆栈上分配数组,而本文的代码在堆上分配数组。这对数组在性能方面的表现有严重的性能影响。
文章还提到,对于不同系统和不同大小的数组,行为可能不是统一的。他的文章专门围绕磁盘缓存的含义展开,这些含义在代码中可能有效,也可能不有效。
在您的情况下,第二个函数更快的原因(我不认为这在任何机器上都能工作)是因为在点处有更好的cpu缓存,您的cpu有足够的缓存来存储数组,您的操作系统需要的东西等等,第二个函数可能会比第一个慢得多。从性能的角度来看。如果有足够多的其他程序运行,我怀疑这两个循环代码会给出更好的性能,因为第二个函数的效率明显不如第一个函数,如果有足够多的其他东西缓存,性能领先抛出缓存将被消除。