どんなことでも

この人 blog を書くのだろうか?

ActivePerl のアップデート方法

2014-08-02 00:55:00 | perl
物のついでなので書いておく。
ActivePerl のアップデートの仕方 ~俺の方法編~


というツイートをヒントに調べてみた。
1. 古いバージョンのパッケージが混ざると面倒な気がするので、ActivePerl のバージョンアップの前に ppm を起動し最新のパッケージへ更新。

2. コマンドプロンプトを開き、以下のコマンドで XML 形式のインストール済みパッケージ一覧をファイルに保存。
ppm profile save %USERPROFILE%\Desktop\ActivePerl_PPM_profile.xml

これで、デスクトップの ActivePerl_PPM_profile.xml というファイルにインストール済みパッケージの一覧が保存されました。
  ※既存のファイルがある場合は上書きされます

3. ActivePerl をアンインストールし、指示に従わず再起動しない。
  ※普通の人は再起動した方が良いと思います。

4. やらなくても良いと思うけど
  C:\Perl とか、D:\Perl64 辺りの、Perl を入れたディレクトリを丸ごと消す。
  ※私の場合は V:\Perl64 でした。

5. 最新の ActivePerl をダウンロードしてきてインストール
  ※2014/08/01時点で
   5.16.3.1604(5.16系), 5.18.2.1802 (5.18系)
   の二つが最新版でした。

6. インストールパッケージの情報を ppm に読み込ませる。
コマンドプロンプトから以下のコマンドを入力。
ppm profile restore %USERPROFILE%\Desktop\ActivePerl_PPM_profile.xml


7. ppm を起動し、パッケージのアップデートをかけると、先ほどの一覧の中でインストールされていないパッケージがインストールされます。

めでたくアップデート完了。

私は上記の方法で 5.14.2 から、5.18.2 へアップグレードしました。

ppm を起動 = スタートメニューから Perl Package Manager を起動するか、「ファイル名を指定して実行」で、ppm と入力すると起動します。

エラトステネスのふるい

2014-08-01 04:39:00 | perl
ActivePerl で書いてみたエラトステネスの篩
# perl
use strict;
use warnings;

# エラトステネスの篩 (Sieve of Eratosthenes)
my $MAX = 10000000;
my @Prime = ();
for (my $i = 2 ; $i <= sqrt($MAX) ; $i++){
# マークが付いていたら (=素数でなかったら) 次へ
if (defined($Prime[$i])){next;}

# 素数の倍数にマークを付ける
for (my $j = 2 ; $MAX >= ($i * $j) ; ++$j ){
$Prime[$i * $j] = 1;
}
}

# マークされていない素数を表示する
for (my $i = 2 ; $i <= $MAX ; ++$i){
if(!defined($Prime[$i]) ){
print "$i,";
}
}


と、ネットで調べてみるともっと短いスクリプトを発見。
grep で、倍数を消してる?さっぱり分からんけど、間違ってはなさそう。悔しいので速度比較をしてみた。
Erat_1 がネットから拾ってきたスクリプト。Erat_2 が私の書いた奴
# perl

use strict;
use warnings;
use Benchmark qw/timethese cmpthese/;

# エラトステネスの篩 (Sieve of Eratosthenes)
my $MAX = 10000000;

my $results = timethese( 1,{
Erat_1 =>
sub {
my $x = $MAX;
my @numbers = (2 .. $x);
my @prime_numbers;
while(1){
if($numbers[0] > sqrt $x){
push @prime_numbers, @numbers;
last;
}
my $number = shift @numbers;
push @prime_numbers, $number;
@numbers = grep { $_ % $number != 0 } @numbers;
}
},

Erat_2 =>
sub {
my $x = $MAX;
my @Prime = ();
for (my $i = 2 ; $i <= sqrt($x) ; $i++){
# マークが付いていたら (=素数でなかったら) 次へ
if (defined($Prime[$i])){next;}

# 素数の倍数にマークを付ける
for (my $j = 2 ; $x >= ($i * $j) ; ++$j ){
$Prime[$i * $j] = 1;
}
}
},

});

cmpthese $results;


表示部分はメインではないので省略。(join が早いのは分かってますが、まぁ、それは置いといて)
Benchmark: timing 1 iterations of Erat_1, Erat_2...
Erat_1: 57 wallclock secs (56.39 usr + 0.08 sys = 56.47 CPU) @ 0.02/s (n=1)
(warning: too few iterations for a reliable count)
Erat_2: 5 wallclock secs ( 5.82 usr + 0.11 sys = 5.93 CPU) @ 0.17/s (n=1)
(warning: too few iterations for a reliable count)
s/iter Erat_1 Erat_2
Erat_1 56.5 -- -90%
Erat_2 5.93 853% --

おぉ、俺の書いた方が 10倍ぐらい早い。push や、shift の配列操作、剰余の計算が重い感じですかねぇ?
って、剰余求めたらエラトステネスの篩じゃない気がする。割り算使っちゃ駄目でしょ。←気づくのが遅い。

そして、100000000 まで求めようとするとネットで調べた方はメモリーを 3G 程使ってまだ足らないと、落ちてしまいました(>_<)
私が書いた方は動いて、99999989 がその中で最大の素数と出ました。メモリの使い方も違いがあるのですねぇ。

正規表現のエラトステネスのふるいを発見。メモリーは使わないですが...鬼のように遅い! (Erat_3)
my $MAX = 20000;
my $results = timethese( -30,{
Erat_1 =>
sub {
...snip...
},

Erat_2 =>
sub {
...snip...
},

Erat_3 =>
sub {
grep { (1 x $_) !~ /^(11+)\1+$/ } (2..$MAX);
},

});

cmpthese $results;

と、2万までの素数を30秒で何回求められるか試したら、
Benchmark: running Erat_1, Erat_2, Erat_3 for at least 30 CPU seconds...
Erat_1: 33 wallclock secs (32.56 usr + 0.02 sys = 32.57 CPU) @ 52.62/s (n=1714)
Erat_2: 33 wallclock secs (32.37 usr + 0.00 sys = 32.37 CPU) @ 141.24/s (n=4572)
Erat_3: 36 wallclock secs (35.60 usr + 0.00 sys = 35.60 CPU) @ 0.03/s (n=1)
(warning: too few iterations for a reliable count)
Rate Erat_3 Erat_1 Erat_2
Erat_3 2.81e-002/s -- -100% -100%
Erat_1 52.6/s 187228% -- -63%
Erat_2 141/s 502721% 168% --

配列 & 剰余 : 32.57秒で1714回 / 1秒間に 52.62回
私の書いたの: 32.37秒で 4572回 / 1秒間に141.24回
正規表現 : 35.60秒で 1回 / 1秒間に 0.03回