PHP로 대용량 계산처리 프로세스를 만들 경우 single thread이므로 CPU의 멀티 코어를 제대로 활용할 수 없음.


PHP를 이용해서 비동기/병렬 실행에 관해서는 아래 문서를 참조하면 여러가지 방법을 확인할 수 있음.

http://www.mullie.eu/parallel-processing-multi-tasking-php/


여기서는 pcntl_fork()를 이용하여 자식 프로세스를 생성하는 방식에 대한 예제만 제시함.

(이게 제일 깔끔하다...)


아래 예제는 job 하나당 제법 계산시간을 소요하는 job 100개를 CPU 프로세서 수만큼 동시에 계산하는 스크립트임.

계산하는 부분은 그냥 usleep으로 퉁쳤음.

$startTime = microtime(true);
 
 
// 동시 실행 프로세스 수
$maxProcCount = getCpuCount();
 
// 실행할 전체 job 카운트
$countJob = 100;
 
 
// 임시로 실행할 job 할당
$jobList = array();
for ($i=0; $i<$countJob; $i++) {
    $jobList[] = array(
        'name'       => 'job'.$i,
        'sleep_time' => floor((mt_rand() / mt_getrandmax()) * 1000) * 1000
    );  
}
 
 
 
 
// 일단 동시 실행 프로세스 수만큼 fork
for ($i=0; $i<$maxProcCount; $i++) {
    $arg = array_shift($jobList);
 
    calculate($arg);
}
 
 
// child process가 죽을 때마다 체크해서 계속 job 할당
while (pcntl_waitpid(0, $status) != -1) {
    //$status = pcntl_wexitstatus($status);
 
    // 처리할 job이 전부 소진되었을 경우 그냥 기다림
    if (count($jobList) < 1) continue;
 
    // job 할당
    $arg = array_shift($jobList);
    calculate($arg);
}
 
// 계산완료
printf("계산완료 (%.3f sec)\n", microtime(true)-$startTime);
 
 
 
 
 
// 처리할 job 데이터를 넘겨받아 child process fork해서 단위계산 수행
function calculate($arg)
{
    $pid = pcntl_fork();
 
    // error
    if ($pid == -1) {
        echo '[ERROR] could not fork'."\n";
        exit;
    }   
    // child
    else if ($pid == 0) {
        // 단위계산 수행
        echo 'JOB '.$arg['name'].' START'."\n";
        usleep($arg['sleep_time']);
        echo 'JOB '.$arg['name'].' COMPLETE'."\n";
        exit;
    }   
    // parent
    else {
    }   
}
 
// CPU 프로세서 수 반환
function getCpuCount()
{
    return substr_count(file_get_contents('/proc/cpuinfo'), 'processor');
}










Posted by bloodguy
,