如何使用PCNTL并行调用php函数

时间:2012-11-02 06:49:05

标签: php parallel-processing

我对不同的服务器有大约10个不同的请求,并且用于在我的网站中的函数调用中按顺序获取响应。

现在,我想为不同的服务器请求并行调用我的函数。一旦我从任何服务器获得第一个响应,然后想要停止剩余的进程。

目前我正在调用我的函数:

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并行运行此代码?

1 个答案:

答案 0 :(得分:11)

关于PCNTL的可用性

PHP内置了一些PCNTL功能,但默认情况下不启用它们。

来自php.net pcntl installation instructions

  

在编译PHP以启用Process Control支持时,您必须使用--enable-pcntl配置选项编译PHP的CGI或CLI版本。


关于并行化

如果您知道机器上的核心数量,那么我建议将工作划分为多个部门。进程控制仅适用于类似* nix的系统,因此您可能有nproc命令可用:

$numberOfProcessors = `nproc`;

fork要获得正确数量的进程,请在它们之间划分工作,然后离开。划分工作可能很困难,但我相信你会弄明白的。


代码转储

我感觉很慷慨所以我继续为你编写了大部分内容。一定要明白它,因为它还没有完成。

注意:

  • 通过调用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);
    }
}