为什么要“ unordered_map”用“结构”钥匙运行如此慢?

发布于 2025-02-07 13:21:54 字数 2474 浏览 1 评论 0原文

我已经使用(i,j,k)坐标为unordered_map中的密钥。但是,当我将更多的键插入其中时,它会在令人震惊的大小上变慢(例如插入 10x 更多的键和消耗 100x 更多的时间,甚至更糟糕)。 Unordered_map现在是我程序的瓶颈,因此我想找出如何改进它。以下是我问题的最低可再现示例:

#include <unordered_map>
#include <time.h>

using namespace std;

// define the key
struct key
{
    int i;
    int j;
    int k;
    key(int a,int b,int c): i(a),j(b),k(c){}
    bool operator==(const key& other_key) const{
        return i==other_key.i && j==other_key.j && k==other_key.k;
    }
};

// define a simple hash function for unordered_map
struct key_hash
{
    size_t operator()(const key& o) const{
        return o.i ^ o.j ^ o.k;
    }
};

// define unordered_map
unordered_map<key,int,key_hash> memory;

int main(int arg,char **argv){
    // accept arguments about how many keys should be inserted
    int I=atoi(argv[1]);
    int J=atoi(argv[2]);
    int K=atoi(argv[3]);

    double st=clock();
    for(int i=0;i<I;i++){
        for(int j=0;j<J;j++){
            for(int k=0;k<K;k++){
                memory[{i,j,k}]=i+j+k;
            }
        }
    }
    double et=clock();
    printf("time: %f",(et-st)/CLOCKS_PER_SEC);
}

我尝试以下参数,结果是:

(i,j,k)时间(sec)
(1,100,100)0.013
(10,100,100)1.285
(100,100,100)327.10088

令人震惊的是,当我通过 10x 增加i时,时间会增加 100x ,甚至更糟。我还使用Python运行相同的逻辑,并获得更合理和更好的结果。以下是Python代码:

import time
if __name__=='__main__':
    I=100
    J=100
    K=100
    memory={}
    st=time.time()
    for i in range(I):
        for j in range(J):
            for k in range(K):
                memory[(i,j,k)]=i+j+k
    et=time.time()
    print('time: {}'.format(et-st))

python的结果在下表中:

(i,j,k)时间(sec)
(1,100,100)0.006
(10,100,100)0.043
(100,100,100)0.3100 0.318

因此在Python中i的增加,时间的增加是相同的,这是合理的。 Python使用的时间也大大减少了。

总之,我的代码是错误的,还是unordered_map不适合我的目的?我该如何解决?

I have used (i, j, k) coordinates as key in an unordered_map. But when I insert more keys into it, it becomes much slower in a shocking magnitude (e.g. insert 10x more keys and consumes 100x more time, and even worse). The unordered_map now is the bottleneck of my program, so I want to find out how to improve it. Following is the minimal reproducible example of my problem:

#include <unordered_map>
#include <time.h>

using namespace std;

// define the key
struct key
{
    int i;
    int j;
    int k;
    key(int a,int b,int c): i(a),j(b),k(c){}
    bool operator==(const key& other_key) const{
        return i==other_key.i && j==other_key.j && k==other_key.k;
    }
};

// define a simple hash function for unordered_map
struct key_hash
{
    size_t operator()(const key& o) const{
        return o.i ^ o.j ^ o.k;
    }
};

// define unordered_map
unordered_map<key,int,key_hash> memory;

int main(int arg,char **argv){
    // accept arguments about how many keys should be inserted
    int I=atoi(argv[1]);
    int J=atoi(argv[2]);
    int K=atoi(argv[3]);

    double st=clock();
    for(int i=0;i<I;i++){
        for(int j=0;j<J;j++){
            for(int k=0;k<K;k++){
                memory[{i,j,k}]=i+j+k;
            }
        }
    }
    double et=clock();
    printf("time: %f",(et-st)/CLOCKS_PER_SEC);
}

I try following arguments and the result is:

(I, J, K)time (sec)
(1, 100, 100)0.013
(10, 100, 100)1.285
(100,100,100)327.178

The shocking thing is that when I increase I by 10x, the time increases by 100x and even worse. I also use python to run the same logic and get much more reasonable and better result. Following is the python code:

import time
if __name__=='__main__':
    I=100
    J=100
    K=100
    memory={}
    st=time.time()
    for i in range(I):
        for j in range(J):
            for k in range(K):
                memory[(i,j,k)]=i+j+k
    et=time.time()
    print('time: {}'.format(et-st))

The result of python is in following table:

(I, J, K)time (sec)
(1, 100, 100)0.006
(10, 100, 100)0.043
(100,100,100)0.318

So in python the increase of I and the increase of time is in the same magnitude, which is reasonable. And the time python used is also significantly less.

In conclusion, is my code wrong or is unordered_map not suitable for my purpose? And how can I solve it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文