std :: vector访问内存的次数几乎是原始指针的两倍-为什么?

时间:2019-02-05 01:35:35

标签: c++

关于std :: vector的内存行为,我有一个相当基本的问题。我想了解为什么通过向量的简单循环比使用原始指针的相同循环要慢得多。

这是代码0:

#include<iostream>
#include<vector>
#include "utils.h" //contains Timer
using namespace std;

void ff(double * p, int n) {

  for (int i =0; i< n ; i++) p[i]+=i;

}

int main() {
  int n = 1e9;
  Timer t;  //comes from "utils.h"
  t.tic();     //start timer
  double * p = new double[n];
  ff(p, n);
  delete[] p;
  double tt = t.toc();     //stop timer
  cout << tt << endl;     // number of seconds recorded by t.
}

编译并运行code0时,得到以下输出:3.88309。

这是codeV:

#include<iostream>
#include<vector>
#include "utils.h"
using namespace std;

void ff(vector<double>& v, int n) {

  for (int i =0; i< n ; i++) v[i]+=i;

}

int main() {
  int n=1e9;
  Timer t;
  t.tic();
  vector<double> v(n);
  ff(v, n);
  double tt = t.toc();
  cout << tt << endl; 
}

编译并运行codeV时,得到以下输出:5.25866。

如您所见,code0和codeV在做同样的事情,但是第一个是通过指针实现的,第二个是通过std :: vector实现的。 但是codeV的速度几乎是code0的两倍。

让我说一下,我编译两个代码时都没有优化标志,而是使用g ++。

出于好奇,我在code0和codeV上运行了valgrind和perf,结果发现:

1)codeV执行455,378,126个缓存引用,而code0仅执行185,640,714;

2)codeV在其内存调用中大约有50%的高速缓存未命中,而code0小于5%。

如果在优化标记为ON的情况下进行编译,则时间差异变小,尽管内存上的差异仍然明显。我想问:这是怎么回事?为什么在这样一个简单的任务上std :: vector的性能比原始指针差很多?

感谢您对此问题的任何见解!

1 个答案:

答案 0 :(得分:2)

没有优化,所有C ++标准库将比C代码慢。如果没有优化,所有C语言都比手写汇编要慢。您期望什么?

与C语言中的单个数组写入相比,为了不经过优化就使用std::vector,编译器必须为写入向量元素写出大约四个函数调用。

至少使用-O2-O3 -DNDEBUG是我的偏爱。也使用-flto-fprofile-generate / -fprofile-use。查找它们。

如果您不打算快速编写C ++,为什么还要使用它呢?