为什么是std :: vector :: operator 比std :: vector :: at()快5到10倍?
在程序优化期间,试图优化循环遍历一个向量,我发现以下事实::: std :: vector :: at()比operator []要慢得多!
在释放和debugging版本(VS2008 x86)中,运算符[]比()的速度快5到10倍 。
在网上阅读让我意识到在()有边界检查。 好的,但是,放慢操作达10倍?!
这有什么理由吗? 我的意思是,边界检查是一个简单的数字比较,还是我错过了什么?
问题是这个性能打击的真正原因是什么?
还有, 有什么办法可以让它更快 ?
我当然会在其他代码部分(我已经有自定义的边界检查!)与[]调用我所有的()调用。
概念validation:
#define _WIN32_WINNT 0x0400 #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <conio.h> #include <vector> #define ELEMENTS_IN_VECTOR 1000000 int main() { __int64 freq, start, end, diff_Result; if(!::QueryPerformanceFrequency((LARGE_INTEGER*)&freq)) throw "Not supported!"; freq /= 1000000; // microseconds! ::std::vector<int> vec; vec.reserve(ELEMENTS_IN_VECTOR); for(int i = 0; i < ELEMENTS_IN_VECTOR; i++) vec.push_back(i); int xyz = 0; printf("Press any key to start!"); _getch(); printf(" Running speed test..\n"); { // at() ::QueryPerformanceCounter((LARGE_INTEGER*)&start); for(int i = 0; i < ELEMENTS_IN_VECTOR; i++) xyz += vec.at(i); ::QueryPerformanceCounter((LARGE_INTEGER*)&end); diff_Result = (end - start) / freq; } printf("Result\t\t: %u\n\n", diff_Result); printf("Press any key to start!"); _getch(); printf(" Running speed test..\n"); { // operator [] ::QueryPerformanceCounter((LARGE_INTEGER*)&start); for(int i = 0; i < ELEMENTS_IN_VECTOR; i++) xyz -= vec[i]; ::QueryPerformanceCounter((LARGE_INTEGER*)&end); diff_Result = (end - start) / freq; } printf("Result\t\t: %u\n", diff_Result); _getch(); return xyz; }
编辑:
现在这个值被认为是“xyz”,所以编译器不会“擦除”它。
原因是未经检查的访问可能可以通过单个处理器指令完成。 一个检查的访问也将不得不从内存中加载大小,比较它与索引,并(假设它在范围内)跳过error handling程序的条件分支。 处理抛出exception的可能性可能会更多。 这会慢很多倍,这正是为什么你有两个select。
如果您可以certificate索引在没有运行时检查的范围内,则使用operator[]
。 否则, at()
使用,或在访问之前添加自己的检查。 operator[]
应该或多或less地尽可能快,但如果索引是无效的,将会混乱地爆炸。
我在我的机器上运行了你的testing代码:
在未经优化的debugging版本中,两个循环之间的差异是微不足道的。
在优化版本构build中,第二个for循环被完全优化(对operator[]
的调用可能内联,优化器可以看到循环没有任何作用,可以删除整个循环)。
如果我改变循环体来做一些实际的工作,例如vec.at(i)++;
和vec[i]++;
,这两个回路之间的差异是微不足道的。
我看不出你看到的五到十倍的性能差异。
你不用做任何事情的返回值,所以如果编译器内联这些函数,它可以完全优化它们。 或者,也许它可以完全脱离下标( []
)版本。 从性能测量的angular度来看,没有优化的运行是没有用处的,你需要的是一些简单而有用的程序来执行这些function,所以它们不会被优化掉。 例如,你可以洗牌vector(随机交换50000对元素)。