在程序优化过程中,我尝试优化一个遍历向量的循环时,发现以下事实:::std::vector::at() 比 operator[] EXTREMELY慢!
在发布和调试版本(VS2008 x86)中,operator[] 比 at() 快5到10倍。
在网上阅读了一些资料后,我意识到 at() 进行了边界检查。好吧,但是,这会使操作减慢多达10倍吗?
这是什么原因?我的意思是,边界检查只是简单的数字比较,还是我漏掉了什么?
问题是造成性能下降的真正原因是什么?
此外,有没有办法使它更快?
我肯定会在其他代码部分(其中已经进行了自定义边界检查!)中将所有的 at() 调用与 [] 交换。
概念证明:
在发布和调试版本(VS2008 x86)中,operator[] 比 at() 快5到10倍。
在网上阅读了一些资料后,我意识到 at() 进行了边界检查。好吧,但是,这会使操作减慢多达10倍吗?
这是什么原因?我的意思是,边界检查只是简单的数字比较,还是我漏掉了什么?
问题是造成性能下降的真正原因是什么?
此外,有没有办法使它更快?
我肯定会在其他代码部分(其中已经进行了自定义边界检查!)中将所有的 at() 调用与 [] 交换。
概念证明:
#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”,因此编译器不会将其“擦除”。
test_int += vec[i]
这样做一些事情。由于您没有对向量元素进行任何操作,编译器可能会完全优化掉它。此外,还可以参考Ben的答案。 - schnaaderat
的问题。 - jww