【发布时间】:2013-06-27 15:28:10
【问题描述】:
我的印象是 std::vector 只是动态数组的一个薄包装器,它们的性能应该是可比的。在 Internet 上的搜索和 stackoverflow 本身也给出了相同的答案。但是,当我自己测试时,我发现了巨大的差异。代码如下。我尝试使用优化标志 -O2 的 VC++ 2012(发布版本)和 MinGW。
new、malloc 和 calloc 的时间大约是 0.005 秒,而 std::vector 在两个编译器上都需要 0.9 秒。是 std::vector 本身就很慢还是我的代码有一些严重的缺陷?
#define _SCL_SECURE 0
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <time.h>
struct timer
{
clock_t start;
timer()
{
start=clock();
}
~timer()
{
double t=static_cast<double>(clock()-start)/CLOCKS_PER_SEC;
printf("%lf\n", t);
}
};
int main()
{
const size_t len=(1<<28);
{
timer t;
int *d=new int[len];
printf("%d\n",d[len-1]);//prevent compiler from optimizing away
//useless allocation and deallocation
delete[] d;
}
{
timer t;
int *d=(int *)malloc(len*sizeof(int));
printf("%d\n", d[len-1]);
free(d);
}
{
timer t;
std::vector<int> d(len);
printf("%d\n", d[len-1]);
}
{
timer t;
int *d=(int *)calloc(len, sizeof(int));
printf("%d\n", d[len-1]);
free(d);
}
return 0;
}
编辑 1
根据建议,我测试了创建动态数组的其他方法
-
new: 0.005 -
malloc: 0.005 -
calloc: 0.005 -
malloc+memset: 1.244 -
vector(len): 1.231 -
vector(len, 0): 1.234 -
vector.reserve(len): 0.005
所以确实违规者是零初始化而不是分配或释放。这意味着如果需要一个零初始化数组,vector 不是可行的方法,即使它有一个默认初始化所有元素的构造函数。
此外,这不仅仅是从我脑海中蹦出来的东西。我的最后一个课程项目是根据花费的时间来评分的,我使用了几个vectors 来分配一个巨大的内存缓冲区而不是new,以确保异常安全,并且因为我们的教科书鼓励使用 STL。直到今天我才意识到我因此而失去了一些分数。悲伤的一天。
编辑 2
今天我在 Ubuntu 13.04 x64 上尝试了 Clang 3.2,std::vector 不再需要花时间来初始化。事实上,vector现在是最快的!也许这毕竟是一个编译器优化问题,而不是在 std::vector 的设计中固有的。
【问题讨论】:
-
您不应该通过大约 1000 次迭代(如果不是更多)来运行测试吗?
-
它是 GCC 4.8.1 上的 even worse 和 -O3。 0.000000 表示除向量之外的所有内容,即 4.09(第二次运行的时间要短得多,即链接)。
-
您应该比较具有相同功能的代码(即您是否阅读过矢量文档?)。您应该比较没有未定义行为的代码。
-
vector和其他代码之间的重要区别在于,vector对内存进行零初始化,而其他代码则不是(calloc除外)。如果将new替换为new int[len](),则它需要与向量一样长的时间。我假设calloc以某种方式进行了优化(例如,它可以请求归零内存,而不是显式地将内存归零)。 -
数组的分配一般是使用时最近最少使用的操作。
标签: c++ performance stl benchmarking