英文:
Perl's 2D hash initialization - do we have any faster way?
问题
I am looking for a fast 2D hash initialization. I know some recommended use undef, but I need it to be 1. I have tested 4 different flavors as below (please ignore the naming, as I am bad at names)
Surprisingly, for_2d_init_array has the fastest execution.
But, i am still not satisfy with it, as when the $limit=4000, it requires roughly 4-5s for complete initialization. Is there any faster way to do so?
I know there is a bit-vector for such application. For now, I would like to maintain such structure.
英文:
I am looking for a fast 2D hash initialization. I know some recommended use undef, but I need it to be 1. I have tested 4 different flavors as below (please ignore the naming, as I am bad at names)
Surprisingly, for_2d_init_array has the fastest execution.
But, i am still not satisfy with it, as when the $limit=4000, it requires roughly 4-5s for complete initialization. Is there any faster way to do so?
I know there is a bit-vector for such application. For now, I would like to maintain such structure.
timethese(-2, {
for_2d_original => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
for(my $j=0; $j<$limit; $j++){
$hash{$i}{$j}=1;
}
}
},
for_2d_map => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
$hash{$i} = {map { $_ => 1 } 0..$limit-1};
}
},
for_2d_init_hash => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
my %tmp_hash;
for(my $j=0; $j<$limit; $j++){
$tmp_hash{$j} = 1;
}
$hash{$i} = \%tmp_hash;
}
},
for_2d_init_hash_w_array => sub {
my %hash;
my $limit = 100;
my @array = (0..$limit-1);
my @init = (1)x$limit;
for(my $i=0; $i<$limit; $i++){
my %tmp_hash;
@tmp_hash{@array} = @init;
$hash{$i} = \%tmp_hash;
}
},
});
Results:
for_2d_original: 3 wallclock secs ( 2.10 usr + 0.00 sys = 2.10 CPU) @ 751.90/s (n=1579)
for_2d_map: 2 wallclock secs ( 2.18 usr + 0.00 sys = 2.18 CPU) @ 559.17/s (n=1219)
for_2d_init_hash: 2 wallclock secs ( 2.15 usr + 0.00 sys = 2.15 CPU) @ 994.42/s (n=2138)
for_2d_init_hash_w_array: 2 wallclock secs ( 2.12 usr + 0.00 sys = 2.12 CPU) @ 1580.19/s (n=3350)
答案1
得分: 1
我从Armali那里得到了一个提示,并用二维数组替换,结果很好。我知道这不再是一个二维哈希,但我认为这个结构很好,因为我只需将{}替换为系统中剩余的遗留代码的[]。谢谢大家。(最初,每行都是不同大小的哈希。)为了完整起见,我包括了代码及其结果。
timethese(-2, {
for_2d_original => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
for(my $j=0; $j<$limit; $j++){
$hash{$i}{$j}=1;
}
}
},
for_2d_map => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
$hash{$i} = {map { $_ => 1 } 0..$limit-1};
}
},
for_2d_init_hash => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
my %tmp_hash;
for(my $j=0; $j<$limit; $j++){
$tmp_hash{$j} = 1;
}
$hash{$i} = \%tmp_hash;
}
},
for_2d_init_hash_w_array => sub {
my %hash;
my $limit = 100;
my @array = (0..$limit-1);
my @init = (1)x$limit;
for(my $i=0; $i<$limit; $i++){
my %tmp_hash;
@tmp_hash{@array} = @init;
$hash{$i} = \%tmp_hash;
}
},
for_2d_init_array => sub {
my $limit = 100;
my @init;
$init[$_] = [(1)x$limit] for 0..$limit-1;
},
});
结果:
for_2d_original: 2秒墙钟时间(2.12秒用户时间+0.00秒系统时间=2.12秒CPU时间)@744.81/s(n=1579)
for_2d_map: 2秒墙钟时间(2.19秒用户时间+0.00秒系统时间=2.19秒CPU时间)@556.62/s(n=1219)
for_2d_init_hash: 2秒墙钟时间(2.21秒用户时间+0.00秒系统时间=2.21秒CPU时间)@978.28/s(n=2162)
for_2d_init_hash_w_array: 2秒墙钟时间(2.15秒用户时间+0.00秒系统时间=2.15秒CPU时间)@1558.14/s(n=3350)
for_2d_init_array: 2秒墙钟时间(2.10秒用户时间+0.00秒系统时间=2.10秒CPU时间)@6018.57/s(n=12639)
英文:
I took a hint from Armali and replace with 2D array and the results is great. I know this is no longer a 2D hash, I consider this structure as fine, as I can just replace {} to [] for the remaining of the legacy code the system have. Thanks all. (initially, it is a variable sizes of hash in each rows. ) For completeness, I included the code and its results.
timethese(-2, {
for_2d_original => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
for(my $j=0; $j<$limit; $j++){
$hash{$i}{$j}=1;
}
}
},
for_2d_map => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
$hash{$i} = {map { $_ => 1 } 0..$limit-1};
}
},
for_2d_init_hash => sub {
my %hash;
my $limit = 100;
for(my $i=0; $i<$limit; $i++){
my %tmp_hash;
for(my $j=0; $j<$limit; $j++){
$tmp_hash{$j} = 1;
}
$hash{$i} = \%tmp_hash;
}
},
for_2d_init_hash_w_array => sub {
my %hash;
my $limit = 100;
my @array = (0..$limit-1);
my @init = (1)x$limit;
for(my $i=0; $i<$limit; $i++){
my %tmp_hash;
@tmp_hash{@array} = @init;
$hash{$i} = \%tmp_hash;
}
},
for_2d_init_array => sub {
my $limit = 100;
my @init;
$init[$_] = [(1)x$limit] for 0..$limit-1;
},
});
Results:
for_2d_original: 2 wallclock secs ( 2.12 usr + 0.00 sys = 2.12 CPU) @ 744.81/s (n=1579)
for_2d_map: 2 wallclock secs ( 2.19 usr + 0.00 sys = 2.19 CPU) @ 556.62/s (n=1219)
for_2d_init_hash: 2 wallclock secs ( 2.21 usr + 0.00 sys = 2.21 CPU) @ 978.28/s (n=2162)
for_2d_init_hash_w_array: 2 wallclock secs ( 2.15 usr + 0.00 sys = 2.15 CPU) @ 1558.14/s (n=3350)
for_2d_init_array: 2 wallclock secs ( 2.10 usr + 0.00 sys = 2.10 CPU) @ 6018.57/s (n=12639)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论