为什么std :: vector :: operator []比std :: vector :: at()快5至10倍? [英] Why is std::vector::operator[] 5 to 10 times faster than std::vector::at()?

查看:111
本文介绍了为什么std :: vector :: operator []比std :: vector :: at()快5至10倍?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在程序优化过程中,尝试优化遍历向量的循环时,我发现以下事实::: std :: vector :: at()比操作符[]慢得多!

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[] !

operator []比at()快5到10倍。调试版本(VS2008 x86)。

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

在网络上阅读一些内容使我意识到at()具有边界检查功能。好的,但是,最多可以将操作速度减慢10倍吗!!

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?

我当然会用其他代码部分的[]交换所有at()调用(

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

概念证明:

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

编辑:

现在将值赋值为


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

推荐答案

原因是未检查的访问可能是 xyz,因此编译器不会擦除它。用单个处理器指令完成。被检查的访问还必须从内存中加载大小,将其与索引进行比较,并且(假设它在范围内)跳过条件分支到错误处理程序。可能会有更多的麻烦来处理引发异常的可能性。这将慢很多倍,这就是为什么您同时拥有这两种选择的原因。

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.

如果您可以证明索引在范围内而无需运行时检查,请使用 operator [] 。否则,请使用 at(),或在访问之前添加您自己的支票。 operator [] 应该尽可能快,但是如果索引无效,它将混乱地爆炸。

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 :: operator []比std :: vector :: at()快5至10倍?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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