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);
}
}