6

私は OS に近いプログラミング手法には関与していませんが、知っているように、Perl で何かを並行して実行する場合に選択する武器はfork、おそらくその上に構築されたいくつかの有用なモジュールです。のドキュメントページにforkは次のように書かれています:

Does a fork(2) system call to create a new process running the same program at the same point.

結果として、多くのメモリを消費する大きなアプリケーションを持ちfork、小さなタスクを呼び出すと、2 つの大きな perl プロセスが存在し、2 つ目のプロセスは単純な作業を行うためだけにリソースを浪費することになります。

問題はfork、コードの切り離された部分を独立して実行し、必要なリソースだけを消費させるために何をすべきか (または、それが唯一の方法である場合はどのように使用するか) です。

非常に単純な例:

    use strict;
    use warnings;

    my @big_array = ( 1 .. 2000000 );  # at least 80 MB memory
    sleep 10;  # to have time to inspect easely the memory usage

    fork();
    sleep 10;  # to have time to inspect easely the memory usage

子プロセスも 80 MB 以上を消費します。

明確にするために: この切り離されたコードと通信したり、その結果を何らかの方法で使用したりすることは重要ではありません。私のリソースを無駄にしないでください!」重い perl アプリケーションを実行している場合。

4

4 に答える 4

3

fork()toexec()はここにいるあなたのバニーです。新しいプロセスをfork()作成し(これはかなり安価な操作です。以下を参照)、実行してexec()いる大きなプロセスを小さなものに置き換えます。perlこれは次のようになります。

use strict;
use warnings;
use 5.010;

my @ary = (1 .. 10_000_000);

if (my $pid = fork()) {
    # parent
    say "Forked $pid from $$; sleeping";
    sleep 1_000;
} else {
    # child
    exec('perl -e sleep 1_000');
}

@ary元のプロセスのメモリを少し埋めるために使用されました。)

fork()元のプロセス全体をコピーしますが、ingは比較的安価であると言いました。これらのステートメントは矛盾していません。設計した人たちforkはこれと同じ問題に気づきました。コピーは遅延です。つまり、実際に変更されたビットのみがコピーされます。

プロセスを相互に通信させたい場合は、IPCのより複雑なドメインに入り始めます。このドメインについては、多くの本が書かれています。

于 2013-02-19T17:20:45.623 に答える
3

フォークされたプロセスは、実際には 80MB の常駐メモリを使用していません。そのメモリの大部分は共有されます。親または子のいずれかがそれに書き込むまで、親プロセスから「借用」されます。その時点で、コピーオンライトセマンティクスにより、メモリが実際にコピーされます。

その荷物を完全に落としたい場合execは、フォークで走ります。これにより、子 Perl プロセスが別の実行可能ファイルに置き換えられ、メモリが解放されます。また、親に何も伝える必要がない場合にも最適です。

于 2013-02-19T17:17:04.893 に答える
1

プロセスのフットプリントのサブセットだけをフォークする方法はないため、通常の回避策は次のようになります。

  1. fork親プロセスでメモリを大量に消費するコードを実行する前
  2. systemまたはで別のプロセスを開始しますopen HANDLE,'|-',...。もちろん、この新しいプロセスは親からデータを継承しないため、何らかの方法でこの子にデータを渡す必要があります。
于 2013-02-19T17:09:05.397 に答える
1

fork()ほとんどのオペレーティング システムに実装されているため、非常に効率的です。一般に、コピー オン ライトと呼ばれる手法を使用します。これは、1 つまたは他のプロセスがページに書き込むまで、ページが最初に共有されることを意味します。また、プロセス メモリの多くは読み取り専用のマップ ファイルになります。

1 つのプロセスが以前に 80MBfork()を使用したからといって、その後 2 つのプロセスが 160MB を使用するわけではありません。各プロセスがより多くのページをダーティにし始めるまでは、最初は 80MB をわずかに超えるだけです。

于 2013-03-12T13:54:05.033 に答える