(Obsolete) Parallel::ForkManager + IPC::Shareable で複数のプロセスで変数を共有する
追記: 2011-12-20T03:18:11+09:00
結構この記事をしばしば参考にして安易にSystemV IPC 共有メモリに突っ込む事をやる人も居るようですが、IPC::Shareable 自体が長い事、メンテされてない上に、SystemV IPC 自体も古くさい手法です。大人しくファイルに書き出すなり、SQLite などを使って保存したりだとか、AnyEvent, Coro 等で書き直すとか、より簡単で確実な方法を試した方が良いでしょう。
つまるところ、この方法はお勧め出来ません。エントリ自体は削除せずに残しておきますが、そのつもりで読んで下さい。
オライリーの Perl クックブックの古い奴のレシピ 16.12 とかに書いてある内容なんですけど、自分でも試してみました。
IPC::Shareable のインストール
残念ながら現在のバージョン 0.60 はそのままだとテストが通りません。
に詳細があります。
次のパッチを当てます。
diff -cr IPC-Shareable-0.60.orig/t/38ipchv.t IPC-Shareable-0.60/t/38ipchv.t *** IPC-Shareable-0.60.orig/t/38ipchv.t 2009-01-12 20:15:16.000000000 +0900 --- IPC-Shareable-0.60/t/38ipchv.t 2009-01-12 20:19:02.000000000 +0900 *************** *** 70,76 **** }); %hv = (); kill ALRM => $pid; ! for (qw(eenie meenie minie moe)) { $ipch->shlock(); $hv{$_} = $$; --- 70,77 ---- }); %hv = (); kill ALRM => $pid; ! sleep 1; ! for (qw(eenie meenie minie moe)) { $ipch->shlock(); $hv{$_} = $$;
IPC-Shareable-0.60.patch とかって名前にしておいて、
$ cd /path/to/dir $ wget http://search.cpan.org/CPAN/authors/id/B/BS/BSUGARS/IPC-Shareable-0.60.tar.gz $ tar xfz IPC-Shareable-0.60 $ cd IPC-Shareable-0.60 $ patch -p1 < ../IPC-Shareable-0.60.patch
としてからいつも通りにインストールします。
サンプル
下記は @data が共有できていないので、最後に dump しても空っぽです。
子プロセス各々にコピーされてしまう訳ですね。
#!/usr/bin/perl use strict; use warnings; use Data::Dump qw(dump); use Perl6::Say; use Parallel::ForkManager; my @data = (); my $pm = Parallel::ForkManager->new(10); for my $i (0..100) { my $pid; $pid = $pm->start && next; push(@data, rand($i)); $pm->finish; } $pm->wait_all_children; say dump(@data);
そこで IPC::Shareable を使うと。
#!/usr/bin/perl use strict; use warnings; use Data::Dump qw(dump); use Perl6::Say; use IPC::Shareable; use Parallel::ForkManager; my $handle = tie my @data, 'IPC::Shareable', undef, { destroy => 1 }; @data = (); my $pm = Parallel::ForkManager->new(10); for my $i (0..100) { my $pid; $pid = $pm->start && next; $handle->shlock; push(@data, rand($i)); $handle->shunlock; $pm->finish; } $pm->wait_all_children; say dump(@data);
とすると @data は shared memory に Storable で保存されるのでプロセス間で共有出来るようになります。
@data は共有変数なんで shlock, shunlock は必要です。
ちなみに tie した後に改めて初期化しないと、上手く動かないです。何もしてないのに shared memory から取得するような感じで落ちてる模様。