문제

편집 : 더 많은 응답을 얻기 위해이 C를 태그로 태그했습니다. 특정 언어 구현보다 내가 관심있는 이론입니다. 따라서 C 코더라면 다음 PHP를 의사 코드로 취급하고 C로 작성된 답변으로 자유롭게 응답하십시오.

Serial 대신 병렬로 작업을 실행하여 PHP CLI 스크립트를 속도를 높이려고합니다. 작업은 서로 완전히 독립적이므로 시작/마감 순서는 중요하지 않습니다.

다음은 원본 스크립트입니다 (이 모든 예제는 명확성을 위해 스트리핑되었습니다).

<?php

$items = range(0, 100);

function do_stuff_with($item) { echo "$item\n"; }

foreach ($items as $item) {
    do_stuff_with($item);
}

나는 그것을 작동하게 만들었습니다 $items 동시에 pcntl_fork() 아래 그림과 같이:

<?php

ini_set('max_execution_time', 0); 
ini_set('max_input_time', 0); 
set_time_limit(0);

$items = range(0, 100);

function do_stuff_with($item) { echo "$item\n"; }

$pids = array();
foreach ($items as $item) {
    $pid = pcntl_fork();
    if ($pid == -1) {
        die("couldn't fork()");
    } elseif ($pid > 0) {
        // parent
        $pids[] = $pid;
    } else {
        // child
        do_stuff_with($item);
        exit(0);
    }   
}

foreach ($pids as $pid) {
    pcntl_waitpid($pid, $status);
}

이제 나는 이것을 연장하여 한 번에 10 명의 어린이 10 명의 어린이가 최대한 활성화되도록하고 싶습니다. 이것을 처리하는 가장 좋은 방법은 무엇입니까? 나는 몇 가지를 시도했지만 운이 많지 않았습니다.

도움이 되었습니까?

해결책

어린이 PID 목록을 얻을 수있는 SyScall은 없지만 ps 당신을 위해 할 수 있습니다.

--ppid 스위치는 프로세스에 대한 모든 어린이를 나열하므로 출력 된 라인 수를 계산하면됩니다. ps.

또는 당신은 당신이 당신의 자신의 카운터를 유지할 수 있습니다. fork() 그리고 감소 SIGCHLD 신호, 가정 ppid 포크 가공을 위해 변경되지 않은 상태로 유지됩니다.

다른 팁

내가 생각해 낼 수있는 가장 좋은 방법은 모든 작업을 대기열에 추가하고 원하는 최대 스레드 수를 시작한 다음 각 스레드에 큐에서 작업을 요청하고 작업을 실행하고 다음 스레드를 요청하고 다음 스레드를 요청하는 것입니다. 더 이상해야 할 일이 없을 때 스레드가 끝나는 것을 잊지 마십시오.

포킹은 비싼 작업입니다. 그것의 외관에서, 당신이 정말로 원하는 것은 멀티입니다스레딩, 멀티가 아닙니다처리. 차이점은 스레드가 가상 주소 공간을 공유하지만 프로세스에는 별도의 가상 주소 공간이 있기 때문에 스레드가 프로세스보다 훨씬 가벼운 중량이라는 것입니다.

저는 PHP 개발자가 아니지만 빠른 Google 검색에 따르면 PHP는 기본적으로 멀티 스레딩을 지원하지 않지만 작업을 수행 할 라이브러리가 있습니다.

어쨌든, 나사산을 생성하는 방법을 알아 내면 스폰 할 스레드 수를 알아 내야합니다. 이렇게하려면 응용 프로그램의 병목 현상이 무엇인지 알아야합니다. 병목 현상 CPU, 메모리 또는 I/O입니까? 귀하는 귀하의 의견에 네트워크가 결합되어 있으며 네트워크는 I/O 유형입니다.

CPU 묶인 경우 CPU 코어만큼이나 많은 병렬성을 얻게 될 것입니다. 더 이상 스레드가 있고 컨텍스트 스위치를 수행하는 데 시간을 낭비하는 것입니다. 스폰 할 총 스레드 수를 알아낼 수 있다고 가정하면 작업을 해당 장치로 나누고 각 스레드 프로세스를 독립적으로 처리해야합니다.

메모리 묶인 경우 멀티 스레딩이 도움이되지 않습니다.

당신은 I/O 묶었 기 때문에 스폰 할 스폰 수를 알아내는 것이 약간 까다 롭습니다. 모든 작업 항목이 분산이 매우 낮은 것으로 처리하는 데 대략 동시에 시간이 걸리면 하나의 작업 항목이 얼마나 오래 걸리는지 측정하여 스폰 할 스폰 수를 추정 할 수 있습니다. 그러나 네트워크 패킷은 매우 가변적 인 대기 시간을 갖는 경향이 있으므로 이는 사실이 아닙니다.

한 가지 옵션은 스레드 풀을 사용하는 것입니다. 전체 스레드를 생성 한 다음 각 항목이 처리하기 위해 풀에 무료 스레드가 있는지 확인합니다. 있으면 해당 스레드가 작업을 수행하고 다음 항목으로 이동합니다. 그렇지 않으면 스레드가 사용될 때까지 기다립니다. 스레드 풀의 크기를 선택하는 것이 중요합니다. 너무 커서 불필요한 컨텍스트 스위치를 수행하는 데 시간을 낭비하고 있습니다. 너무 적고 스레드를 너무 자주 기다리고 있습니다.

또 다른 옵션은 멀티 스레딩/멀티 프로세싱을 포기하고 대신 비동기 I/O를 수행하는 것입니다. 단일 코어 프로세서에서 작업하고 있다고 언급 했으므로 이것이 가장 빠른 옵션 일 것입니다. 같은 기능을 사용할 수 있습니다 socket_select() 소켓에 데이터를 사용할 수 있는지 테스트합니다. 그렇다면 데이터를 읽을 수 있습니다. 그렇지 않으면 다른 소켓으로 이동합니다. 이를 위해서는 더 많은 부기를 수행해야하지만 다른 소켓에서 데이터를 사용할 수있을 때 한 소켓에 데이터가 들어 오기를 기다리지 않습니다.

스레드와 비동기 I/O를 피하고 멀티 프로세싱을 고수하려는 경우, 당기 프로세싱이 충분히 비싸면 여전히 가치가있을 수 있습니다. 그런 다음 그렇게하는 작업 부문을 수행 할 수 있습니다.

$my_process_index = 0;
$pids = array();

// Fork off $max_procs processes
for($i = 0; $i < $max_procs - 1; $i++)
{
  $pid = pcntl_fork();
  if($pid == -1)
  {
    die("couldn't fork()");
  }
  elseif($pid > 0)
  {
    // parent
    $my_process_index++;
    $pids[] = $pid
  }
  else
  {
    // child
    break;
  }
}

// $my_process_index is now an integer in the range [0, $max_procs), unique among all the processes
// Each process will now process 1/$max_procs of the items
for($i = $my_process_index; $i < length($items); $i += $max_procs)
{
  do_stuff_with($items[$i]);
}

if($my_process_index != 0)
{
  exit(0);
}

Man 2 setrlimit

그것은 사용자 당이 될 것입니다 5월 어쨌든 당신이 원하는 것이 되십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top