C ++代码速度,哪个更快?

时间:2013-10-19 00:36:40

标签: c++

是的,这是一个功课问题,我只需要朝着正确的方向努力

C ++的哪个代码块更快,为什么?我认为它是最顶级的,因为[i]数组正在按顺序使用,或者我错在这里?。

    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;
    }
 }

2 个答案:

答案 0 :(得分:8)

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

我们可以猜测位置和缓存行为将如何影响该时间(并且您的猜测是好的),但猜测并不能代替分析。 (见:How can I profile C++ code running in Linux?

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

为什么没有区别:

  • 整个10000个元素可以放入缓存中,使上述优化无法实现。

我无法想到为什么第二个会更快,但我之前感到惊讶。

答案 1 :(得分:5)

最常见的答案是:您需要对两个块进行分析并根据经验查看结果。

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

Ulrich Drepper has a nice paper about this。他在该论文中的一个例子展示了这两个代码块的确切区别。

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

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