3

さまざまなサーバーに対して約 10 の異なる要求があり、Web サイトの関数呼び出しに対して順番に応答を取得していました。

ここで、さまざまなサーバー要求に対して関数を並行して呼び出したいと考えています。いずれかのサーバーから最初の応答を取得したら、残りのプロセスを停止したいと考えています。

現在、私は自分の関数を次のように呼び出しています:

my_launch(1);
my_launch(2);
my_launch(3);
my_launch(4);
my_launch(5);
my_launch(6);
my_launch(7);
my_launch(8);
my_launch(9);
my_launch(10);  

これは順次実行されます。PCNTL を使用してこのコードを並行して実行するにはどうすればよいですか?

4

1 に答える 1

13

PCNTL の可用性について

PHP にはいくつかの PCNTL 機能が組み込まれていますが、デフォルトでは有効になっていません。

php.net pcntl インストール手順から:

プロセス制御サポートを有効にするために PHP をコンパイルするときは、PHP の CGI または CLI バージョンを --enable-pcntl 構成オプションでコンパイルする必要があります。


並列化について

マシンのコア数がわかっている場合は、作業をその数の分割に分割することをお勧めします。プロセス制御は *nix ライクなシステムでのみ機能するため、次のnprocコマンドを使用できる可能性があります。

$numberOfProcessors = `nproc`;

適切な数のプロセスを実行するためにforkし、それらの間で作業を分割して、作業を開始します。仕事の分担は難しいかもしれませんが、きっと分かっていただけると思います。


コードダンプ

私は寛大に感じていたので、先に進んでそのほとんどをコーディングしました。まだまだ未完成なのでご理解ください。

ノート:

  • を呼び出して使用可能なプロセッサnprocの数を取得します。そのため、そのユーティリティがない場合は、作成するプロセスの数に置き換える必要があります。
  • 要求された反復よりも多くのプロセッサが利用可能である場合、それは壊れません。単純に使用するプロセッサが少なくなります。
  • プロセスの数が反復の数に均等に分割されない場合、親プロセスが残りの反復を取得します。
  • 最初の結果が利用可能になった後も停止しません。これを行うには、反復ごとに 1 つのプロセスが必要です。メイン プロセスは、最初のプロセスが終了したときにpcntl_waitを呼び出し、他のプロセスを強制終了する必要があります。

コード:

$procs = `nproc`;
$iterations = 10;
$pids = array();
$iproc = -1;

if ($procs > $iterations) {
    $procs = $iterations;
}

function my_launch($i, $proc) {
    echo "Process $proc ran iteration $i.\n";
}

$pid = 0;
for ($i = 0; $i < $procs; $i++) {
    $pid = pcntl_fork();
    if ($pid > 0) {
        // I am the parent process
        $pids[$pid] = $pid;

    } elseif ($pid == -1) {
        //error occurred, use available processes only
        $nproc = $i;
        break;

    } else {
        //I am the child process.
        $iproc = $i;
        break;
    }
}

$nproc = !empty($nproc) ? $nproc : $procs;

if ($nproc == 0) {
    echo "NOTICE: Process could not be forked; proceeding in serial.\n";
    for ($i = 0; $i < $iterations; $i++) {
        my_launch($i, $iproc);
    }
    exit;
}

if ($nproc != $procs) {
    echo "NOTICE: Only using $nproc processes out of the hoped $procs.\n";
}

$iterationsPerProcess = (int) ($iterations / $nproc);

// children do the main work.
if ($pid == 0) {
    $stopAt = $iterationsPerProcess * ($iproc + 1);

    for ($i = ($iproc * $iterationsPerProcess); $i < $stopAt; $i++) {
        my_launch($i, $iproc);
    }
}

if ($pid > 0) {
    // parent process picks up the remainder of the work
    $i = $nproc * $iterationsPerProcess;
    for (; $i < $iterations; $i++) {
        my_launch($i, "Main");
    }

    //wait for children to finish
    $status = -1;
    foreach ($pids as $createdIndex => $pid) {
        pcntl_waitpid($pid, $status);
    }
}
于 2012-11-07T17:10:33.510 に答える