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

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

问题描述

在程序优化期间,尝试优化一个遍历向量的循环,我发现以下事实:::std::vector::at() 比 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[] !

operator[] 比 at() 快 5 到 10 倍,无论是在 release 还是在调试版本 (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..
");

    { // 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		: %u

", diff_Result);

    printf("Press any key to start!");
    _getch();
    printf(" Running speed test..
");

    { // 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		: %u
", diff_Result);
    _getch();
    return xyz;
}


现在该值被分配给xyz",因此编译器不会擦除"它.


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.

如果您可以在没有运行时检查的情况下证明索引在范围内,则使用 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天全站免登陆