简体   繁体   English

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

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

I have got here two programs with me, both are doing exactly the same task. 我和我在这里有两个程序,两个程序完成相同的任务。 They are just setting an boolean array / vector to the value true. 它们只是将布尔数组/向量设置为值true。 The program using vector takes 27 seconds to run whereas the program involving array with 5 times greater size takes less than 1 s. 使用向量的程序需要27秒才能运行,而涉及大小为5倍的数组的程序则需要不到1秒。 I would like to know the exact reason as to why there is such a major difference ? 我想知道为什么会有这么大的差异的确切原因? Are vectors really that inefficient ? 载体真的效率低吗?

Program using vectors 程序使用向量

#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;
}

Runtime - 27 seconds 运行时 - 27秒

Program using Array 使用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;
}

Runtime - < 1 seconds 运行时间 - <1秒

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

Thanks 谢谢

Amare 阿玛雷

You're using std::vector of bool and that's not what you think it is! 你正在使用bool的std :: vector,这不是你想象的那样!

vector of bool is a bastard child template specialization that should never have existed and actually stores 1 bool in each bit. bool的矢量是一个不应该存在的混蛋子模板专业化,实际上每个位存储1个bool。 Accesses into it are more complicated due to masking and shifting logic, so will definitely be somewhat slower. 由于屏蔽和移位逻辑,访问它会更复杂,因此肯定会慢一些。

Click here for some info on vector of bool. 点击这里查看关于bool矢量的一些信息。

Also, you may be running an unoptimized build (almost certainly given the times you listed, 27 seconds is outrageous for 4 million iterations). 此外,您可能正在运行未经优化的构建(几乎可以肯定的是,在您列出的时间内,对于400万次迭代,27秒是令人发指的)。 The Standard Template Library relies very heavily on the optimizer to do things like inline function calls and elide temporaries. 标准模板库非常依赖于优化器来执行内联函数调用和elide temporaries等操作。 Lack of this optimization causes an especially heavy performance degradation for vector of bool because it has to return a proxy object when you index into it, because you can't take the address of a bit, so operator [] can't return a reference. 缺少这种优化会导致bool向量性能特别严重,因为它在索引时必须返回一个代理对象,因为你不能取一点地址,所以operator []不能返回一个引用。

Click here for more info on proxied containers (The last half is about vector of bool) 点击这里获取有关代理容器的更多信息 (后半部分是关于bool的矢量)

In addition many STL implementations have helpful debugging bits that are not part of the standard which help you catch bugs, but really drag performance down. 此外,许多STL实现都有有用的调试位,这些位不是标准的一部分,可以帮助您捕获错误,但实际上会降低性能。 You'll want to make sure those are disabled in your optimized build. 您需要确保在优化的构建中禁用了这些功能。

Once you turn on the optimizer, have the right settings (ie no STL debugging turned on), and are actually testing the same thing in both loops, you will see almost no difference. 一旦你打开优化器,有正确的设置(即没有打开STL调试),并且实际上在两个循环中测试相同的东西,你将看到几乎没有差异。

I had to make your loop much larger to test on my machine, but here's two builds of your vector of bool loop on my machine, showing the impact of optimizer flags on STL code 我必须让你的循环更大才能在我的机器上进行测试,但是这里有两个我的机器上的bool循环向量构建,显示了优化器标志对STL代码的影响

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

Other answers are very good, but you could easily answer it yourself by this method . 其他答案非常好,但你可以通过这种方法轻松自己回答。

ADDED: In response to comments, let me show you what I mean. 补充:回应评论,让我告诉你我的意思。 I'm running VC On Windows, but this works on any language/OS. 我正在运行VC On Windows,但这适用于任何语言/操作系统。 I took your first program and increased size to 20000 so it would run long enough. 我拿了你的第一个程序,并将大小增加到20000,所以它可以运行足够长的时间。 Then while it was running, I took several stackshots. 然后在它运行的时候,我拍了几张照片。 They all look like this: 他们都看起来像这样:

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()

So what that says is that it is spending essentially all of it's time in the indexing operation on line 24, and the reason it's spending that time is that the [] operator is calling the begin operator. 那么什么,说的是,它基本上花光了它的时间在索引操作上线24,它的花费当时的原因是[]操作者调用begin操作。 In more detail: 更详细:

main() line 24 + 12 bytes

is this code: 是这段代码:

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

that calls: 那叫:

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

which is this code (that I reformatted a little bit): 这是代码(我重新格式化了一下):

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

that calls: 那叫:

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

which is doing this (in more detail): 这样做(更详细):

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

What it is doing is writing 68 bytes of 0xCC on the stack (for some debug reason) as part of getting the begin address of the vector, as part of computing the address of v[i] , prior to doing the assignment. 它正在做的是在堆栈上写入68字节的0xCC (出于某些调试原因),作为获取向量的begin地址的一部分,作为在执行赋值之前计算v[i]的地址的一部分。

The fraction of time it spends doing this is near 100%, because it was doing it on every one of the several samples that were taken. 它花费的时间比例接近100%,因为它是在拍摄的几个样本中的每一个上进行的。 Could you have guessed that that's what it was spending nearly all of its time doing? 您是否已经猜到这就是几乎所有时间都在做的事情? I couldn't have. 我不能。

This is, of course, a Debug build. 当然,这是一个Debug构建。 If you switch to a Release build, but turn on debugging information, all these functions get inlined and optimized away, so it goes like 30 times faster, and again the stackshots tell exactly what it's doing. 如果您切换到Release版本,但打开调试信息,所有这些函数都会被内联并优化掉,因此它的速度提高了30倍,而且stackshots再次告诉它正在做什么。

So - people can tell you what it might be doing, but this shows how to find out for yourself what it is really doing. 所以 - 人们可以告诉你它可能在做什么,但这显示了如何自己找出它真正在做什么。

On your environment it will undoubtedly be different. 在您的环境中,它无疑会有所不同。

std::vector<bool> is optimized for memory consumption rather than performance. std::vector<bool>针对内存消耗而非性能进行了优化。

You may trick it by using std::vector<int> . 你可以使用std::vector<int>来欺骗它。 You should not have performance drawbacks then. 那你不应该有性能上的缺点。

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

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