为什么std :: vector的速度是原始数组的两倍?包含完整代码

时间:2014-04-06 22:36:13

标签: c++ arrays performance optimization vector

结果:

  

矢量时间:7051

     

阵列时间:18944

我为此使用了MSVC释放模式,编译为32位。

在此测试之前,我正在查看GCC的矢量源代码并且感到惊讶,因为我认为operator[]检查了数组越界,但事实并非如此。但是,我没想到矢量这么快?!

完整代码:

#include <iostream>
#include <vector>

int main(){
    const int size = 10000;
    unsigned long long my_array[size];
    std::vector<unsigned long long> my_vec;

    my_vec.resize(size);

    //Populate containers
    for(int i=0; i<size; i++){
        my_vec[i] = i;
        my_array[i] = i;
    }

    //Initialise test variables
    unsigned long long sum = 0;
    unsigned long long time = 0;
    unsigned long long start = 0;
    unsigned long long finish = 0;

    //Time the vector
    start = __rdtsc();
    for(int i=0; i<size; i++){
        sum += my_vec[i];
    }
    finish = __rdtsc();


    time = finish - start;
    std::cout << "Vector time: " << time << "     " << sum << std::endl;


    sum = 0;

    //Time the array
    start = __rdtsc();
    for(int i=0; i<size; i++){
        sum += my_array[i];
    }
    finish = __rdtsc();

    time = finish - start;
    std::cout << "Array time: " << time << "     " << sum << std::endl;

    int t = 8;
    std::cin >> t;
    return 0;
}

2 个答案:

答案 0 :(得分:10)

以下是使用MSVC 2013。

对于矢量:

0019138E  mov         edi,edi  
  for (int i = 0; i<size; i++){
00191390  lea         ecx,[ecx+20h]  
    sum += my_vec[i];
00191393  movdqu      xmm0,xmmword ptr [ecx-20h]  
00191398  paddq       xmm1,xmm0  
0019139C  movdqu      xmm0,xmmword ptr [ecx-10h]  
001913A1  paddq       xmm2,xmm0  
001913A5  dec         esi  
001913A6  jne         main+0F0h (0191390h)  
  }

对于数组:

0019142D  lea         ecx,[ecx]  
  for (int i = 0; i<size; i++){
00191430  lea         ecx,[ecx+20h]  
    sum += my_array[i];
00191433  movdqu      xmm0,xmmword ptr [ecx-30h]  
00191438  paddq       xmm1,xmm0  
0019143C  movdqu      xmm0,xmmword ptr [ecx-20h]  
00191441  paddq       xmm2,xmm0  
00191445  dec         esi  
00191446  jne         main+190h (0191430h)  
  }

如您所见,内环是相同的。实际上,怀疑它是硬件的东西,我交换了两个循环,数组更快地到达相同的边距(实际上,在现实世界中,它们都不比其他更快或更慢)。

我预测这是某种CPU缓存行为: https://en.wikipedia.org/wiki/CPU_cache

答案 1 :(得分:0)

我们有两个80,000字节的数组。首先,160,000字节并行填充数据。然后读取其中80,000个,然后读取其他80,000个。假设一个128,000字节的缓存:

读取向量的前32,000个字节时,不会缓存数据。接下来的48,000个字节被缓存。现在缓存包含所有向量,以及最后48,000个字节的数组。但是数组中的字节是最旧的,因此从一开始就读取数组,结尾处的数据被抛出。因此,数组中的所有读取都是未缓存的。

因此,对于向量,我们有32,000字节的未缓存读取和48,000字节缓存读取,而对于数组,则有80,000字节未缓存的读取。

高速缓存大小为128,000字节。其他尺寸会有所不同。 但那时可能会发生完全不同的事情。您的代码可以在运行时切换到不同的处理器,此时一个处理器可能必须将数据写入主内存,另一个处理器可以读取它。在另一个方向上,操作系统可能刚刚意识到正在进行某些操作并将处理器从省电模式转变为某种涡轮模式。

进行单一测量并从中得出结论不会考虑这些因素。