:: std :: vector :: at()vs operator []<<惊人的结果! 5到10倍更慢/更快! [英] ::std::vector::at() vs operator[] << surprising results!! 5 to 10 times slower/faster!

查看:164
本文介绍了:: std :: vector :: at()vs operator []<<惊人的结果! 5到10倍更慢/更快!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在程序优化期间,尝试优化循环通过向量循环,我发现了以下事实::: std :: vector :: at()是比运算符[]更慢EXTREMELY



运算符[]的速度比at()快5到10倍,调试版本(VS2008 x86)。



在web上阅读一点,让我意识到at()有边界检查。好吧,但是,将操作速度降低多达10倍?!



有什么原因吗?我的意思是,边界检查是一个简单的数字比较,或者我错过了什么?

问题是什么是这种性能命中的真正原因?

此外,



我肯定会用其他代码部分中的[]替换所有我的at()调用

概念证明:

 <$> c $ c> #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不支持!
freq / = 1000000; //微秒!

:: std :: vector< int> vec;
vec.reserve(ELEMENTS_IN_VECTOR);
for(int i = 0; i vec.push_back(i);

int xyz = 0;

printf(按任意键开始!);
_getch();
printf(Running speed test..\ n);

{// at()
:: QueryPerformanceCounter((LARGE_INTEGER *)& start);
for(int i = 0; i xyz + = vec.at(i);
:: QueryPerformanceCounter((LARGE_INTEGER *)& end);
diff_Result =(end - start)/ freq;
}
printf(Result\t\t:%u\\\
\\\
,diff_Result);

printf(按任意键开始!);
_getch();
printf(Running speed test..\ n);

{// operator []
:: QueryPerformanceCounter((LARGE_INTEGER *)& start);
for(int i = 0; i xyz - = vec [i];
:: QueryPerformanceCounter((LARGE_INTEGER *)& end);
diff_Result =(end - start)/ freq;
}

printf(Result\t\t:%u\\\
,diff_Result);
_getch();
return xyz;
}

编辑:

现在, xyz,因此编译器不会擦除它。

解决方案

原因是未经检查的访问可能是用单个处理器指令完成。检查的访问也必须从内存加载大小,与索引进行比较,并且(假设它在范围内)跳过一个条件分支到错误处理程序。可能会有更多的处理抛出异常的可能性。这将是许多倍慢,这正是为什么你有两个选项。



如果你可以证明索引是在范围内没有运行时检查,然后使用 operator [] 。否则,使用在(),或在访问之前添加您自己的检查。 operator [] 应该尽可能快,但如果索引无效则会爆炸。


During program optimization, trying to optimize a loop that iterates through a vector, I found the following fact: ::std::vector::at() is EXTREMELY slower than operator[] !

The operator[] is 5 to 10 times faster than at(), both in release & debug builds (VS2008 x86).

Reading a bit on the web got me to realize that at() has boundary checking. Ok, but, slowing the operation by up to 10 times?!

Is there any reason for that? I mean, boundary checking is a simple number comparison, or am I missing something?
The question is what is the real reason for this performance hit?
Further more, is there any way to make it even faster?

I'm certainly going to swap all my at() calls with [] in other code parts (in which I already have custom boundary check!).

Proof of concept:

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

Edit:
Now the value is being assiged to "xyz", so the compiler will not "wipe" it out.

解决方案

The reason is that an unchecked access can probably be done with a single processor instruction. A checked access will also have to load the size from memory, compare it with the index, and (assuming it's in range) skip over a conditional branch to the error handler. There may be more faffing around to handle the possibility of throwing an exception. This will be many times slower, and this is precisely why you have both options.

If you can prove that the index is within range without a runtime check then use operator[]. Otherwise, use at(), or add your own check before access. operator[] should be more or less as fast as possible, but will explode messily if the index is invalid.

这篇关于:: std :: vector :: at()vs operator []&lt;&lt;惊人的结果! 5到10倍更慢/更快!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆