Google
    
<< TOPページ 掲示板TOP 記事データ お知らせメール ▼レス(1) >>

Perl : ベンチマーク : ハッシュへの代入

 ( メビウスリング日記 )
- アクセス(89) - いいね!(0)

あうら☆マスター ★管理者


ベンチマークを取った所、文末の4例では実行速度が異なりました。

「比較1」ではループごとに、同じハッシュキーに値 を代入し続けています。 ( $hash{'key'} = 1; )
「比較2」ではループごとに、異なるハッシュキーに値を代入し続けています。 ( $hash{$_} = 1; )

結果 「比較2」 の方が実行が遅くなります。
これは 「比較2」 の場合、ループごとに新しくハッシュキー生成する必要があるためだと思いますので、納得の行く結果でした。

しかし不思議なのは 「比較3」 です。

これは 「比較1」 とほぼ同じ処理なのですが、
1ループごとに異なる値を代入し値づけているにも関わらず、「比較1」 よりも実行速度が速いのです。
( 内容的には $hash{'key'} = 1; $hash{'key'} = 2; $hash{'key'} = 3; )

ちなみに $hash{'key'} = undef; を実行した場合とほぼ同じ速度でした 。

これはどう説明できるかと考える場合、ハッシュに $_ の値をセットする場合、for の各ループを実行した時点で $_ は既に定義済みのため、新しく値を定義するよりも、速度が優れているということかもしれません。

しかしさらに不思議なのは 「比較4」 です。
これは(「比較1」よりも速かった) 「比較2」 とほぼ同じように、値として 1 ではなくて $_ を代入し続けています。

もし前述の結果を考えるならば、「比較2」 より 「比較4」 の方が速度的に優れているはずではないでしょうか。
しかし、今度はその逆なのです。

これは Perl の仕様なのか、それともスクリプトの実行環境や Benchmark.pm の性質によるものかは分かりません。

しかし理由を考えるとするならば、実行時にハッシュー $hash{$_} が生成された時点で、 $_ のマジックが失われ、Perl は $_ を内部的に再定義しなおす必要があるのではないでしょうか。
もしくは他なんらかの処理が行われている可能性がありそうです。

この $_ の再定義(?)と思われる動作のせいで、4つの処理の中で最も遅くなっているのではないかと想像します。
( ちなみに my $key = $_; など、スカラーへの代入ではこの現象は起こりませんでした )

この推測が当たっているかどうかは分かりませんが、とても不思議な現象でした。

──────────────────────────────
スクリプト
──────────────────────────────

use Benchmark;
use strict;

my $try = 50_000;

# 表示
timethese($try, {'TEST1' => '&test1;', 'TEST2' => '&test2;', TEST3 => '&test3;' , TEST4 => '&test4;' });

#-----------------------------------------------------------
# 比較1
#-----------------------------------------------------------

sub test1 {

my %hash;

for(1..100){
$hash{'key'} = 1;
}

}

#-----------------------------------------------------------
# 比較2
#-----------------------------------------------------------

sub test2 {

my %hash;

for(1..100){
$hash{$_} = 1;
}


}

#-----------------------------------------------------------
# 比較3
#-----------------------------------------------------------
sub test3 {

my %hash;

for(1..100){
$hash{'key'} = $_;
}

}

#-----------------------------------------------------------
# 比較4
#-----------------------------------------------------------
sub test4 {

my %hash;

for(1..100){
$hash{$_} = $_;
}


}


──────────────────────────────
実行結果
──────────────────────────────

Benchmark: timing 50000 iterations of TEST1, TEST2, TEST3, TEST4...
TEST1: 1 wallclock secs ( 0.66 usr + 0.00 sys = 0.66 CPU) @ 76219.51/s (n=50000)
TEST2: 1 wallclock secs ( 1.64 usr + 0.00 sys = 1.64 CPU) @ 30525.03/s (n=50000)
TEST3: 1 wallclock secs ( 0.55 usr + 0.00 sys = 0.55 CPU) @ 91575.09/s (n=50000)
TEST4: 3 wallclock secs ( 2.57 usr + 0.00 sys = 2.57 CPU) @ 19425.02/s (n=50000)

6年前 No.0
ページ: 1


 
 

ブルーマニア@aotomizu ★AU=TFfSDwKh1C

速さを求めるのは良いことだと思います。
・・・まぁ僕の場合それがかなり苦手な部類に入ってると個人的には思ってるんですけどね(ぁ

6年前 No.1
ページ: 1

 
 
<< TOPページ 掲示板TOP 記事データ お知らせメール ▲ページ上 >>
★必ず ローカルルールメビウスリングのルール をご覧ください。
 ▼スタンプ▲スタンプ
※スタンプはいちどに 3個 まで使えます  ×閉じる