0

最終更新:説明の仕方がわかりませんが、問題はもう発生していません。それを解決するために何が変わったのかがわかったら、回答を投稿します。

16 コアの Fedora 17 マシンで多数の同様のコマンドを実行するために使用する一連の perl スクリプトがあります。これまでのところ、コマンドの生成方法を変更する必要があるたびに、古いスクリプトの 1 つをテンプレートとして使用して新しいスクリプトを作成していますが、これまでコードで問題が発生したことはありません (まあ、私がとにかく、スクリプトの元のセット)。古いスクリプトでもエラーなく動作することに注意することが重要です。そのため、これはシステムの問題ではないと思います。コードを (おそらく) めちゃくちゃにした場所に主に焦点を当てています。

これは、作業スクリプトのトリミングされたバージョンです。

use Forks::Super MAX_PROC => 24, ON_BUSY => 'block';
#...
foreach my $fi (@FILES){
    #...
    $runMe = 'java -Xmx2048m weka.classifiers.'. $class .' -t '. $TR .' -T '. $TE .' -c 1 > '. $OUT;
    fork { cmd =>  $runMe};
    #...
}
waitall;
print("\nDone!\n");

壊れたスクリプトのトリミングされたバージョンを次に示します。

use Forks::Super MAX_PROC => 24, ON_BUSY => 'block';
#...
foreach my $n (@FI){
    if($n =~ m/^\d+$/){
            #...
        foreach my $f (@files){
            if($f =~ m/(\d+).arff/){
                print "starting interval $1 ... \n";
                #...
                $runMe = 'java -Xmx2048m weka.classifiers.'. $class .' -t '. $TR .' -T '. $TE .' -c 1 > '. $OUT;
                fork { cmd =>  $runMe );                
            }
        }
    }
}
waitall;
print("\nDone!\n");

これはスクリプトの出力 (一部) です。

starting interval 12 ...
starting interval 3 ...
sh: fork: retry: No child processes
starting interval 30 ...
starting interval 6 ...
Use of uninitialized value $signal_pid in print at /usr/local/share/perl5/Forks/Super/Job.pm line 991, <DATA> line 261.
Use of uninitialized value $exec_pid in waitpid at /usr/local/share/perl5/Forks/Super/Job.pm line 918, <DATA> line 261.

エラーsh: fork: retry: No child processesuninitialized value $signal_pid、およびuninitialized value $exec_pidは、一見ランダムなポイントで何度も出力に表示され、プログラムの実行時間が長くなるにつれてますます多くなります。

更新: Forks::Super に設定した 24 に加えて、このリモート マシンで実行している 4 つのターミナルよりもはるかに多くの$ ulimit -aリターンが返されます。max user processes (-u) 1024他のスクリプトが正常に動作し、これが を返すNo child processesことを考えると、2 番目のスクリプトで作成したすべてのプロセスをクリーンアップ/待機してはいけないと思います。最初のスクリプトと 2 番目のスクリプトの呼び出しの違いがわかりませんwaitall

更新:Forks::Super::Debug => 1オプション を使用した場合の代表的な出力を次に示します。

starting interval 30 ...
14694 23:24:05.735:  New job created: {pid=;state=NEW;cmd=java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_files/$
14703 23:24:05.735:  Signal pid for 14703 is 14708
14694 23:24:05.736:  fork(): {pid=;state=NEW;style=cmd;cmd=[java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_file$
14694 23:24:05.736:  _can_launch(): system not busy. launch ok.
14694 23:24:05.736:  fork: launch approved for job
14694 23:24:05.736:  Job will use /bar/.fhfork14694/.fh_007.signal to get signal pid.
14707 23:24:05.737:  Executing command [ java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /home/share/data/arff_files/trainers_l1o_curv$
Use of uninitialized value $signal_pid in print at /usr/local/share/perl5/Forks/Super/Job.pm line 991, <DATA> line 261.
Use of uninitialized value $signal_pid in concatenation (.) or string at /usr/local/share/perl5/Forks/Super/Job.pm line 995, <DATA> lin$
14707 23:24:05.737:  Signal pid for 14707 is
Use of uninitialized value $exec_pid in waitpid at /usr/local/share/perl5/Forks/Super/Job.pm line 918, <DATA> line 261.
14707 23:24:05.737:  waitpid returned -1, exit code of 14707 was -1 72057594037927935
starting interval 6 ...
14694 23:24:05.739:  New job created: {pid=;state=NEW;cmd=java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_files/$
14694 23:24:05.739:  fork(): {pid=;state=NEW;style=cmd;cmd=[java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_file$
14694 23:24:05.739:  _can_launch(): system not busy. launch ok.
14694 23:24:05.740:  fork: launch approved for job
14694 23:24:05.740:  Job will use /bar/programs/.fhfork14694/.fh_008.signal to get signal pid.
14694 23:24:05.740:  launch(): CORE::fork() returned undefined!
current file is 2

問題は、新しいプロセスの作成に間に合うようにプロセスが停止/クリーンアップされていないことだと確信しています。私が両親を殺す前と後ps -auxの両方の最初の50行に現れていないにもかかわらず、多くの子供たちが走っていることに同意します. topこのwaitall;呼び出しは、子が生きている間にスクリプトが終了するのMAX_PROC => 24を防ぐ必要があり、一度に 24 を超える子が開始されるのを防ぐ必要があります。

これwaitallが私のトラブルの原因だった場合、スクリプトが連続して呼び出されるたびに問題が悪化する可能性があり、これが私が見ていることです。しかし、これが事実である場合、私は自分が何をしているのかを見るべきではありませんtop. を見ているtopと、最初に 24 人の子が実行されているのが見えます。最初の実行が終了すると、chldren の数がなくなるまで減少し、再び実行され、別の 24 の子が実行されます...これは他のスクリプトで見られる通常のパターン。しかし、後で、またはスクリプトを強制終了して (タスクに関連するプロセスが生きていないことを確認するためにpkill perlとを使用pkill java)、再度開始すると、多数のエラー メッセージと、小さいながらも散発的な数の子が に表示されtopます。

4

2 に答える 2

1

これに関して私が見つけたものを共有しているだけです。

作業中のスクリプトにはループが 1 つだけ含まれており、壊れたスクリプトにはネストされたループが含まれています。

sh: fork: retry: No child processes

No child processes は、これ以上 fork できないというシステム エラーです。そのため、実行時にコードがさらに多くのプロセスを fork する可能性があり、このエラーが発生しました。

MAX_PROC => 24

1 回の実行に 24 個のプロセスしか与えていません。この 24 個を超えるプロセスをフォークしようとすると、プロセスON_BUSY => 'block'は待機し、成功するまで子の作成を再試行します。モジュールのドキュメントForks::Superでは、システムの fork 呼び出しが失敗すると失敗すると述べています。エラーから、システムがそれ以上のフォークに失敗したことは明らかです。変数を追加して、$count++フォークされるプロセスの数を見つけるだけです。Forks::Super::DEBUGも試してみてください。より多くの手がかりが得られるかもしれません。

$ ulimit -aプロセスの最大数を返すのではなく、実際にはユーザーが実行できるスレッドの最大数を返します。ps aux現在実行中のプロセスをより明確に把握できるようにしてください。

于 2012-07-18T05:44:24.203 に答える