最近做一定规模的数据读取,二维vector,行约300k,每列大约10~100个int。一直在纠结以下问题:
- 方法一:在循环的外边预先声明一个vector(预申请足够大空间),然后在循环内部做
resize
操作,然后对应位置直接赋值 - 方法二:在循环的外边预先声明一个vector(预申请足够大空间),然后在循环内部做
clear
操作,然后再用push_back
插入 - 方法三:每次在循环中声明一个vector局部变量(预申请足够大空间),用
push_back
插入
显然
内存拷贝
是vector最耗时的操作,所以上述都在声明时直接指定需要的空间。如果不知道需要的空间,则取可能情况中足够大的即可。
上述三种方法是否有明显的时间差异?
直观上来说,第一种、第二种相较于第三种应该是更加快一些的,因为没有局部vector的构造与销毁。但是,方法一与方法三哪个更快呢?
当然要写代码做实验。
不过,在写之前,加入一组猜想地、可能最慢的对照实验:在方法三的基础上,每次声明vector时定义一个默认vector,即不预申请空间。定义其为方法0 ;
实验设置
平台及编译器:RedHat , GCC 4.8.5
迭代轮次: 0x100000 (1M) 次
实验结果
方法 | 时间(s) |
---|---|
Method 0 (In + No-Alloc + push_back ) | 13.2011 |
Method 1 (Out + Pre-Alloc + Resize + assign) | 1.61622 |
Method 2 (Out + Pre-Alloc + Clear + push_back ) | 10.9568 |
Method 3 (In + Pre-Alloc + assign) | 2.43724 |
结果总结
实验结果不得不说有点让人吃惊啊….
- 使用外部定义且预申请空间的方法2竟然耗时与内部定义+不预申请空间的方法0在一个量级… 而他们的共同点是,用了
push_back
- 即使每次在循环内部声明局部vector且预申请空间,但最后时间差距与方法1差别不大。
WHY
难道push_back
会导致内存的重新分配? 官方文档说:
This effectively increases the container size by one, which causes an automatic reallocation of the allocated storage space if -and only if- the new vector