简体   繁体   English

为什么在unordered_map中使用find()要比直接读取快得多?

[英]Why use find() in unordered_map is much faster than directly read?

Its hard to describe so I will just show the code: 很难描述所以我只会显示代码:

#include <bits/stdc++.h> 
using namespace std; 

int main() 
{ 
    clock_t start, end; 
    unordered_map<int, int> m;
    long test=0;
    int size = 9999999;
    for (int i=0; i<size/3; i++) {
        m[i] = 1;
    }
    start = clock(); 
    for (int i=0; i<size; i++) {
        //if (m.find(i) != m.end())
            test += m[i];
    }
    end = clock(); 
    double time_taken = double(end - start) / double(CLOCKS_PER_SEC); 
    cout << "Time taken by program is : " << fixed  
         << time_taken << setprecision(5); 
    cout << " sec " << endl; 
    return 0; 
} 

The result(3 times): Without if (m.find(i) != m.end()) : 结果(3次):没有if (m.find(i) != m.end())

Time taken by program is : 3.508257 sec 
Time taken by program is : 3.554726 sec 
Time taken by program is : 3.520102 sec 

With if (m.find(i) != m.end()) 使用if (m.find(i) != m.end())

Time taken by program is : 1.734134 sec 
Time taken by program is : 1.663341 sec 
Time taken by program is : 1.736100 sec 

Can anyone explain why? 有谁能解释为什么? What really happened inside add m[i] when the key not appeared? 当密钥没有出现时,添加m [i]里面真正发生了什么?

In this line 在这一行

test += m[i];

the operator[] does two things: First it tries to find the entry for the given key, then if the entry does not exist it creates a new entry. operator[]做两件事:首先它试图找到给定键的条目,然后如果条目不存在则创建一个新条目。

On the other hand here: 另一方面,这里:

if (m.find(i) != m.end())
        test += m[i];

the operator[] does only one thing: It finds the element with the given key (and because you checked before that it exists, no new entry has to be constructed). operator[]只做一件事:它找到具有给定键的元素(并且因为在它存在之前检查过它,所以不必构造新的条目)。

As the map contains only keys up to size/3 your results suggest that creating the element outweights the overhead for first checking if the element does exist. 由于地图仅包含size/3键,因此结果表明创建元素会超过首先检查元素是否存在的开销。

In the first case there are size elements in the map while in the second there are only size/3 elements in the map. 在第一种情况下,地图中有size元素,而在第二种情况下,地图中只有size/3元素。 Note that calling operator[] can get more expensive the more elements are in the map. 请注意,调用operator[]会使地图中的元素越多越昂贵。 It is Average case: constant, worst case: linear in size. 它是平均情况:恒定,最坏情况:线性大小。 and the same holds for find . 同样适用于find However, calling the methods many times, the worst case should amortize and you are left with average constant. 但是,多次调用这些方法,最坏的情况应该是摊销,而你是平均常数。

Thanks to Aconcagua, for pointing out that you did not reserve space in the map. 感谢Aconcagua,指出你没有预留地图中的空间。 In the first case you add many elements that require to allocate space, while in the second, the size of the map stays constant during the part you measure. 在第一种情况下,您添加了许多需要分配空间的元素,而在第二种情况下,地图的大小在您测量的部分期间保持不变。 Try to call reserve before the loop. 尝试在循环之前调用reserve Naively I would expect that the loops would be very similar in that case. 天真的我会期望在这种情况下循环非常相似。

The difference with and without the if is down to you having only populated the first third of the map. 有和没有if的区别在于你只填充了地图的前三分之一。

If you do a find, then the program will go and find the element, and if it exists then it will do the operator[], which finds it again (not terribly efficient), find it exists, and return the value 如果你做了一个find,那么程序将去找到元素,如果它存在,那么它将执行operator [],它再次找到它(不是非常有效),找到它存在,并返回值

Without the if, when you do the operator[]. 没有if,当你做运算符[]时。 it will try and find the element, fail, and create the element (with the default value for an int, which is 0), and return it 它将尝试找到元素,失败并创建元素(使用int的默认值,即0),并返回它

So without the if, you are populating the whole map, which will increase the runtime. 因此,如果没有if,则填充整个映射,这将增加运行时间。

If you wanted to be more efficient, you could use the result of the find to fetch the value 如果您想提高效率,可以使用find的结果来获取值

auto iter = m.find(i);
if (iter != m.end()) 
{
    test += iter->second;
}        

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM