关于 PCNTL 可用性
PHP 内置了一些 PCNTL 功能,但默认情况下不启用它们。
来自php.net pcntl 安装说明:
在编译 PHP 以启用进程控制支持时,您必须使用 --enable-pcntl 配置选项编译 PHP 的 CGI 或 CLI 版本。
关于并行化
如果您知道机器上的内核数量,那么我建议您将工作分成这么多部分。进程控制仅适用于 *nix-like 系统,因此您可能有nproc
可用的命令:
$numberOfProcessors = `nproc`;
你分叉以获得适当数量的进程运行,在它们之间分配工作,然后你就走了。划分工作可能很困难,但我相信你会弄清楚的。
代码转储
我感觉很慷慨,所以我继续为你编写了大部分代码。一定要理解它,因为它还没有完全完成。
笔记:
- 通过调用 获取可用处理器的数量
nproc
,因此如果您没有该实用程序,则应将其替换为您想要创建的进程数。
- 如果您有比请求的迭代更多的处理器可用,它不会中断。它只是使用更少的处理器。
- 如果进程数没有平均分配到迭代次数,则父进程将拾取剩余的迭代次数。
- 在第一个结果可用后不会停止。为了做到这一点,每次迭代都需要一个进程。当第一个进程完成并杀死其他进程时,主进程应该调用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);
}
}