哪一个会更快

GG.*_*GG. 1 c c++ performance refactoring

只需在代码中略微修改即可计算两个数组的总和

int main()

{

    int a[10000]={0};   //initialize something
    int b[10000]={0};   //initialize something

    int sumA=0, sumB=0;

    for(int i=0; i<10000; i++)
    {
        sumA += a[i];
        sumB += b[i];
    }
        printf("%d %d",sumA,sumB);

}
Run Code Online (Sandbox Code Playgroud)

要么

int main()

{

    int a[10000]={0};   //initialize something
    int b[10000]={0};   //initialize something

    int sumA=0, sumB=0;

    for(int i=0; i<10000; i++)
    {
        sumA += a[i];

    }

        for(int i=0; i<10000; i++)
    {       
        sumB += b[i];
    }
        printf("%d %d",sumA,sumB); 
}
Run Code Online (Sandbox Code Playgroud)

哪个代码会更快.

Rik*_*ood 25

只有一种方法可以知道,那就是测试和测量.您需要找出瓶颈所在的位置(CPU,内存带宽等).

数组中的数据大小(示例中为int)会影响结果,因为这会对处理器缓存的使用产生影响.通常,您会发现示例2更快,这基本上意味着您的内存带宽是限制因素(示例2将以更有效的方式访问内存).

  • >只有一种方法可以知道,那就是测试和测量你可能已经停在那里:) (9认同)

Ski*_*izz 9

这是使用VS2005构建的一些定时代码:

#include <windows.h>
#include <iostream>
using namespace std;
int main ()
{
  LARGE_INTEGER
    start,
    middle,
    end;

  const int
    count = 1000000;

  int
    *a = new int [count],
    *b = new int [count],
    *c = new int [count],
    *d = new int [count],
    suma = 0,
    sumb = 0,
    sumc = 0,
    sumd = 0;

  QueryPerformanceCounter (&start);
  for (int i = 0 ; i < count ; ++i)
  {
    suma += a [i];
    sumb += b [i];
  }
  QueryPerformanceCounter (&middle);
  for (int i = 0 ; i < count ; ++i)
  {
    sumc += c [i];
  }
  for (int i = 0 ; i < count ; ++i)
  {
    sumd += d [i];
  }
  QueryPerformanceCounter (&end);
  cout << "Time taken = " << (middle.QuadPart - start.QuadPart) << endl;
  cout << "Time taken = " << (end.QuadPart - middle.QuadPart) << endl;
  cout << "Done." << endl << suma << sumb << sumc << sumd;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

运行此版本,后一版本通常更快.

我尝试编写一些汇编程序来击败第二个循环,但我的尝试通常较慢.所以我决定看看编译器生成了什么.这是为第二个版本中的主要求和循环生成的优化汇编程序:

00401110  mov         edx,dword ptr [eax-0Ch] 
00401113  add         edx,dword ptr [eax-8] 
00401116  add         eax,14h 
00401119  add         edx,dword ptr [eax-18h] 
0040111C  add         edx,dword ptr [eax-10h] 
0040111F  add         edx,dword ptr [eax-14h] 
00401122  add         ebx,edx 
00401124  sub         ecx,1 
00401127  jne         main+110h (401110h) 
Run Code Online (Sandbox Code Playgroud)

这是注册用法:

  • eax =用于索引数组
  • ebx =总计
  • ecx =循环计数器
  • edx =在循环的一次迭代中访问的五个整数的总和

这里有一些有趣的事情:

  • 编译器已将循环展开五次.
  • 内存访问顺序不连续.
  • 它在循环中间更新数组索引.
  • 它总计五个整数然后将其加到总计中.

要真正理解为什么这么快,你需要使用英特尔的VTune性能分析器来查看CPU和内存停滞的位置,因为这段代码非常违反直觉.


Jor*_*oba 7

理论上,由于缓存优化,第二个应该更快.

缓存经过优化,可以传输和保留数据块,因此对于第一次访问,您将获得第一个数据块的大部分进入缓存.在第一个代码中,可能会发生当您访问第二个阵列时,您可能需要取出第一个阵列的一些数据,因此需要更多访问.

在实践中,这两种方法将花费或多或少的同时,考虑到实际缓存的大小,并且根本没有数据被从缓存中取出,这是第一种方法.

注意:这听起来很像家庭作业.在这些尺寸的现实生活中,第一个选项会稍快一些,但这只适用于这个具体的例子,嵌套循环,更大的阵列或特别小的缓存大小会对性能产生重大影响,具体取决于顺序.


小智 5

第一个会更快.编译器不需要重复循环两次.虽然工作量不大,但在增加循环变量和执行检查条件时会丢失一些循环.