C++ code speed, which is faster?

use*_*951 1 c++

Yes this is a homework question i just need a push in the right direction

Which code block of C++ is faster and why? I Think it is the top one because the [i] array is being used in order, or am i wrong here?.

    double A[100][100];
    ...
    for (int i = 0; i < 100; i++) {
        for (int j = 0; j < 100; j++) {
            A[i][j] = i * j;
        }
     }


    double A[100][100];
    ...
    for (int j = 0; j < 100; j++) {
    for (int i = 0; i < 100; i++) {
        A[i][j] = i * j;
    }
 }
Run Code Online (Sandbox Code Playgroud)

小智 8

如果不运行和分析代码,就无法知道哪条代码更快.

我们可以猜测局部性和缓存行为将如何影响该时间(并且您的猜测是好的),但猜测不能替代分析.(请参阅:如何分析在Linux中运行的C++代码?)

第一个版本可能更快的一个原因:

为什么没有区别:

  • 整个10000个元素可以适合缓存,从而使上述优化无法实现.

我想不出有什么理由为什么第二个会更快,但我以前一直很惊讶.

  • @ user1789951这是生活中令人遗憾的事实,编程教授很少是优秀的程序员,并经常教导不好的做法,过时的,有时甚至是错的. (6认同)
  • +一些编译器现在明白这一点,并会为你做循环交换. (2认同)

Cra*_*rks 5

最一般的答案是:您需要分析两个块并根据经验查看结果.

但是,我可以为大多数具有分层缓存的现代x86,x64,PPC和ARM处理器提供答案.在这些平台上,由于更好的数据局部性,最上面的一个会更快:它按顺序访问内存地址,因此您将更频繁地访问数据缓存.智能x86和x64实现甚至会注意到您正在以这种方式顺序读取内存,并在需要之前预取下一个缓存行.底部模式在远程地址上不间断地访问内存,这意味着您可能会在每次读取时错过缓存.

Ulrich Drepper有一篇很好的论文.他在该论文中的一个例子展示了这两个代码块的确切区别.

作为这里的数学示例,假设您正在编写具有64字节高速缓存行大小的Intel Corei7和32kb L1数据高速缓存.这意味着每次获取地址时,处理器也将获取该64字节对齐块中的所有其他数据.在该平台上,double是8个字节,因此每个缓存行适合8个字节.因此,顶部示例平均会错过八次迭代中的一次:在每次未命中之后,接下来的56个字节也将被提取,因此接下来的七次双*读取将在高速缓存中.

底部示例可能同时将100行数据(每行一个i)放入缓存中:100*64 = 6400字节,完全在缓存大小内.但是你也可能会超过关联缓存,这意味着两条线将映射到L1中的相同SRAM,这意味着一条线将驱逐另一条线.

  • @JBently如果编译器可以确定没有任何别名这些地址(即通过`restrict`并且在该循环中没有其他指针访问),并且它知道缓存特性,并且它比我安装的GCC版本更聪明,它可以将最底层的例子变成最顶层的例子. (2认同)