2012-11-02 19 views
3

我對於不同的服務器有大約10個不同的請求,並且用於在我的網站的函數調用中分別獲得響應。如何使用PCNTL並行調用php函數

現在,我想爲不同的服務器請求並行調用我的函數。一旦我從任何服務器獲得第一個響應,然後想要停止剩餘的進程。

目前,我打電話給我的功能,像這樣:

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並行運行此代碼?

回答

11

關於PCNTL可否訂購

PHP具有內置的一些功能PCNTL但它們不是默認啓用的。

php.net pcntl installation instructions

你必須編譯PHP來實現過程控制的支持,當編譯PHP的CGI或CLI版本--enable-了pcntl配置選項。


關於並行

如果你知道你的機器上的內核數量,那麼我會建議將工作分成許多部門。過程控制只能在* 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); 
    } 
}