繁体   English   中英

C ++向量与数组(时间)

[英]C++ Vector vs Array (Time)

我和我在这里有两个程序,两个程序完成相同的任务。 它们只是将布尔数组/向量设置为值true。 使用向量的程序需要27秒才能运行,而涉及大小为5倍的数组的程序则需要不到1秒。 我想知道为什么会有这么大的差异的确切原因? 载体真的效率低吗?

程序使用向量

#include <iostream>
#include <vector>
#include <ctime>

using namespace std;

int main(){
 const int size = 2000;
 time_t start, end;
 time(&start);
 vector<bool> v(size);
 for(int i = 0; i < size; i++){
  for(int j = 0; j < size; j++){
   v[i] = true;
  }
 }
 time(&end);
 cout<<difftime(end, start)<<" seconds."<<endl;
}

运行时 - 27秒

使用Array编程

#include <iostream>
#include <ctime>

using namespace std;

int main(){
 const int size = 10000; // 5 times more size
 time_t start, end;
 time(&start);
 bool v[size];
 for(int i = 0; i < size; i++){
  for(int j = 0; j < size; j++){
   v[i] = true;
  }
 }
 time(&end);
 cout<<difftime(end, start)<<" seconds."<<endl;
}

运行时间 - <1秒

平台 - Visual Studio 2008操作系统 - Windows Vista 32位SP 1处理器英特尔(R)奔腾(R)双CPU T2370 @ 1.73GHz内存(RAM)1.00 GB

谢谢

阿玛雷

你正在使用bool的std :: vector,这不是你想象的那样!

bool的矢量是一个不应该存在的混蛋子模板专业化,实际上每个位存储1个bool。 由于屏蔽和移位逻辑,访问它会更复杂,因此肯定会慢一些。

点击这里查看关于bool矢量的一些信息。

此外,您可能正在运行未经优化的构建(几乎可以肯定的是,在您列出的时间内,对于400万次迭代,27秒是令人发指的)。 标准模板库非常依赖于优化器来执行内联函数调用和elide temporaries等操作。 缺少这种优化会导致bool向量性能特别严重,因为它在索引时必须返回一个代理对象,因为你不能取一点地址,所以operator []不能返回一个引用。

点击这里获取有关代理容器的更多信息 (后半部分是关于bool的矢量)

此外,许多STL实现都有有用的调试位,这些位不是标准的一部分,可以帮助您捕获错误,但实际上会降低性能。 您需要确保在优化的构建中禁用了这些功能。

一旦你打开优化器,有正确的设置(即没有打开STL调试),并且实际上在两个循环中测试相同的东西,你将看到几乎没有差异。

我必须让你的循环更大才能在我的机器上进行测试,但是这里有两个我的机器上的bool循环向量构建,显示了优化器标志对STL代码的影响

$ g++ main.cpp 
$ ./a.out 
17 seconds.
$ g++ -O2 main.cpp 
$ ./a.out 
1 seconds.

其他答案非常好,但你可以通过这种方法轻松自己回答。

补充:回应评论,让我告诉你我的意思。 我正在运行VC On Windows,但这适用于任何语言/操作系统。 我拿了你的第一个程序,并将大小增加到20000,所以它可以运行足够长的时间。 然后在它运行的时候,我拍了几张照片。 他们都看起来像这样:

std::vector<bool,std::allocator<bool> >::begin() line 93 + 25 bytes
std::vector<bool,std::allocator<bool> >::operator[]() line 132 + 37 bytes
main() line 24 + 12 bytes
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817077()

那么什么,说的是,它基本上花光了它的时间在索引操作上线24,它的花费当时的原因是[]操作者调用begin操作。 更详细:

main() line 24 + 12 bytes

是这段代码:

for(int j = 0; j < size; j++){
==> v[i] = true;
}

那叫:

std::vector<bool,std::allocator<bool> >::operator[]() line 132 + 37 bytes

这是代码(我重新格式化了一下):

reference operator[](size_type _P){
==> return (*(begin() + _P));
}

那叫:

std::vector<bool,std::allocator<bool> >::begin() line 93 + 25 bytes

这样做(更详细):

92:       iterator begin()
93:           {return (_First); }
00402890   push        ebp
00402891   mov         ebp,esp
00402893   sub         esp,44h
00402896   push        ebx
00402897   push        esi
00402898   push        edi
00402899   push        ecx
0040289A   lea         edi,[ebp-44h]
0040289D   mov         ecx,11h
004028A2   mov         eax,0CCCCCCCCh
004028A7   rep stos    dword ptr [edi]
004028A9   pop         ecx    <===============
004028AA   mov         dword ptr [ebp-4],ecx
004028AD   mov         eax,dword ptr [ebp-4]
004028B0   mov         eax,dword ptr [eax+4]
004028B3   pop         edi
004028B4   pop         esi
004028B5   pop         ebx
004028B6   mov         esp,ebp
004028B8   pop         ebp
004028B9   ret

它正在做的是在堆栈上写入68字节的0xCC (出于某些调试原因),作为获取向量的begin地址的一部分,作为在执行赋值之前计算v[i]的地址的一部分。

它花费的时间比例接近100%,因为它是在拍摄的几个样本中的每一个上进行的。 您是否已经猜到这就是几乎所有时间都在做的事情? 我不能。

当然,这是一个Debug构建。 如果您切换到Release版本,但打开调试信息,所有这些函数都会被内联并优化掉,因此它的速度提高了30倍,而且stackshots再次告诉它正在做什么。

所以 - 人们可以告诉你它可能在做什么,但这显示了如何自己找出它真正在做什么。

在您的环境中,它无疑会有所不同。

std::vector<bool>针对内存消耗而非性能进行了优化。

你可以使用std::vector<int>来欺骗它。 那你不应该有性能上的缺点。

暂无
暂无

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

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