繁体   English   中英

又一个动态阵列与std :: vector,但是

[英]Yet another Dynamic Array vs. std::vector, but

......好吧,我得到了奇怪的结果!

我很好奇std::vector与动态数组的性能。 看来已经有很多关于这个问题的问题,如果我不经常得到这些“矛盾的”结果,我就不会提到它: vector<int>new int[]更快! 我一直认为如果有任何性能差异,它总是喜欢动态数组。 这个结果怎么可能?

代码如下:

int numElements = 10000000;
 long j = 0;
 long k = 0;

 vector<int> intVector(numElements);
 int* intArray = new int[numElements]; 

 clock_t start, finish;
 start = clock();

 for (int i = 0; i < numElements; ++i)
  intVector[i] = i;
 for (int i = 0; i < numElements; ++i)
  j += intVector[i];

 finish = clock();
 cout << "j: " << j << endl;
 cout << "Total duration: " << (double) finish - start << " ms." << endl;

 // Test Control.
 start = clock();

 for (int i = 0; i < numElements; ++i)
  intArray[i] = i;
 for (int i = 0; i < numElements; ++i)
  k += intArray[i];

 finish = clock();
 cout << "k: " << k << endl;
 cout << "Total duration: " << (double) finish - start << " ms." << endl;

优化已经开启,我在每个开始/结束块中分离了for循环,这样我就可以单独计算数组/向量的初始化时间(在这种情况下, std::vector<int>new int[]似乎执行相同的操作)。

但是,使用上面的代码我经常得到std::vector<int>26-30 ms获胜而new int[]36-45 ms

任何人都在关心解释为什么矢量比动态数组表现更好? 两者都是在时序循环之前声明的,所以我预计性能大致相同。 此外,我尝试了相同的想法,而不是使用std::vector<int*>new int*[]并获得了类似的结果, vector类的性能优于动态数组,因此指针指针也是如此。

谢谢您的帮助。

附录:如果没有优化, std::vector会失去一个动态数组的大时间(~ 1,400 ms vs.~ 80 ms ),以达到预期的性能差异,但这并不意味着矢量类可以某种方式优化到提供比标准动态阵列更好的性能?

我的猜测是,操作系统在首次访问之前不会分配物理内存。 vector构造函数将初始化所有元素,因此内存将在您开始计时时分配。 阵列内存未初始化(并且可能未分配),因此其时间可能包括分配。

尝试将数组初始化更改为int* intArray = new int[numElements](); 对其元素进行值初始化,看看是否会改变结果。

出于所有实际目的,当使用这种方式时,它们的速度完全相同。 vector的operator []通常像[MSVC版本]一样实现:

const_reference operator[](size_type _Pos) const
{   // subscript nonmutable sequence
    return (*(_Myfirst + _Pos));
}

......这与:

const_reference operator[](size_type _Pos) const
{   // subscript nonmutable sequence
    return _Myfirst[_Pos];
}

您的测试基本上只是测试编译器内联代码的能力,而且它似乎在这里做得很好。

至于差异的解释,你得到的任何答案通常都是假设的,没有看到反汇编。 它可能与更好的缓存有关,寄存器更好地用于第一种情况(尝试交换测试的顺序,看看会发生什么),等等。值得注意的是,在测试开始之前,将访问向量的内存。它将所有内容初始化为ctor中的T()。

不幸的是,我们不能简单地编写这样的小测试,并从中得出一般结论。 在系统和优化编译器变得如此复杂之前,我们曾经能够做到这一点,但是现在除了现实世界的测试之外,还有太多的变量可以用来做出有意义的结论。

出于同样的原因,我们通常期望任何认真对待性能的人积极地分析他们的代码,因为事情已经变得非常复杂,人们无法正确地确定代码中的瓶颈,而不是明显的算法效率低下(我经常看到专业程序员对装配和计算机体系结构的理解远远超过我在使用剖析器检查他们的假设时所犯的错误。

我刚做了这个实验。 确实有奇怪的行为,虽然我认为我弄清楚了。

再次重复您的代码。 那是...

benchmark vector
benchmark array

benchmark vector
benchmark array

你会注意到第二次你会得到不同的数字。 我猜? 页面错误。 由于某种原因,向量不会导致页面错误,而数组方法会导致页面错误。 页面加载后,两者将以大致相同的速度运行(即:第二次发生的情况)。 到目前为止,有谁知道如何打印进程中的页面错误数?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM