为什么要“ unordered_map”用“结构”钥匙运行如此慢?
我已经使用(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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论