昨日に引き続き3章を読み進めていたら、フィボナッチ数をキャッシュで高速化する例が。
Higher-Order Perl: Transforming Programs with Programs
Mark Jason Dominus
Morgan Kaufmann / 6402円 ( 2005-03-28 )
Mark Jason Dominus
Morgan Kaufmann / 6402円 ( 2005-03-28 )
コードはこんな感じで、割と普通な。
my %cache; sub fib{ my $n = shift; unless (exists $cache{$n}){ if($n < 2){ $cache{$n} = 1; }else{ $cache{$n} = fib($n-1) + fib($n-2); } } return $cache{$n}; }
さて、昨日のタプルを使ったコードとどっちが速いのか比べてみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #!/usr/bin/perl use strict; use warnings; use Benchmark qw(cmpthese); sub fibStep { my $n = shift; return [$n->[1], $n->[0] + $n->[1]]; } sub fibPair { my ($n, $fs, $fp) = @_; return [0,1] if ($n == 0); return $fs->($fp->($n-1,$fs,$fp)) } sub fastFib { my $n = shift; my $fs = \&fibStep; my $fp = \&fibPair; my $fib_num = $fp->($n,$fs,$fp); return $fib_num->[0]; } my %cache; sub fib{ my $n = shift; unless (exists $cache{$n}){ if($n < 2){ $cache{$n} = 1; }else{ $cache{$n} = fib($n-1) + fib($n-2); } } return $cache{$n}; } my $number = 50; my $count = 10000000; my $fibcache = \&fib; my $fibfast = \&fib; cmpthese($count, { 'Cache' => $fibcache->($number), 'Fast' => $fibfast->($number) }); |
とりあえず1000万回まわしてみたけどそれでもwarningがでるので、この際無視。
./fib.pl (warning: too few iterations for a reliable count) (warning: too few iterations for a reliable count) Rate Fast Cache Fast 38461538/s -- -27% Cache 52631579/s 37% --
キャッシュしたほうが速いというのがイマイチ理解できん。何でじゃろか?