Nasıl çatallı çocuk azami miktar zorlayabilir?

4 Cevap php

EDIT: Ben daha yanıt almak için bir umut, bu C etiketli ettik. Daha ben belirli bir dil uygulaması daha ilgileniyorum teori. Yani bir C kodlayıcı iseniz pseudo-kod olarak aşağıdaki PHP tedavi ve C ile yazılmış bir cevap ile cevap çekinmeyin

Ben yerine seri bir paralel olarak görevlerini yürütmek suretiyle bir PHP CLI komut hızlandırmak için çalışıyorum. Görevler bu yüzden onlar içeri / bitirmek başladığı sırası önemli değildir birbirinden tamamen bağımsız

İşte özgün senaryo (netlik için bütün bu örnekler vardır elimden geri unutmayın) bulunuyor:

<?php

$items = range(0, 100);

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

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

Ben paralel $items üzerinde çalışmak yapmayı başardı pcntl_fork() , aşağıda gösterildiği gibi oldum:

<?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);
}

Şimdi öylesine bir anda maksimum aktif 10 çocuk, diyelim ki, orada bu uzatmak istiyorum. Bu işleme en iyi yolu nedir? Ben birkaç şey denedim ama çok şans olmadı.

4 Cevap

Orada çocuk PIDlerin bir listesini almak için hiçbir çağrısı, ancak ps sizin için bunu yapabilirsiniz.

Bunu sadece ps tarafından çıkarılan satırları saymak gerekir işlemek için --ppid switch tüm çocukları listeler.

Alternatif ppid fork'ed işlenmiş boyunca değişmeden kalır varsayarak, sen fork() ve SIGCHLD sinyaline eksiltme üzerinde artacaktır kendi sayacı koruyabilirsiniz.

Ben kadar gelebilir en iyi şey, bir sıraya tüm görevler eklemek istediğiniz parçacığı sayısını başlatın ve ardından kuyruğundan bir görevi isteyen her konu var, görevi yürütmek ve sonraki talep etmektir. Yapmak için daha fazla görevler vardır zaman konuları sonlandırmak zorunda unutmayın.

Çatallanan pahalı bir işlemdir. Bunun görünüyor itibaren, ne gerçekten istediğiniz multi ** parçacığı **, çok değil ** işleme ** olduğunu. Fark konuları bir sanal adres alanı paylaşmak ama süreçler ayrı bir sanal adres alanı var çünkü ipler, süreçler çok daha hafiftir olmasıdır.

Ben bir PHP geliştiricisi değilim, ama hızlı bir Google arama PHP doğal mulithread desteklemediği ortaya koymaktadır, ancak işi yapmak için kütüphaneler vardır.

Eğer konuları yumurtlamaya anlamaya bir kez Neyse, sen yumurtlamak için kaç konuları anlamaya gerekir. Bunu yapmak için, uygulamanızın darboğaz ne olduğunu bilmek gerekir. Darboğaz CPU, bellek veya I / O mi? Eğer ağ bağlı olduğunu yorumlarınızı belitmişsin ve ağ I / O bir türüdür

Eğer CPU bağlı olsaydı, yalnızca CPU çekirdeğine sahip kadar paralellik almak için gidiyoruz; daha fazla iş parçacığı ve sadece zaman bağlam anahtarlarının yapıyoruz harcıyorsun. Eğer birçok birimler halinde işinizi bölmek gerekir, yumurtlamak için toplam kaç konuları anlamaya, ve bağımsız olarak her konu süreç tek bir birim olabilir varsayarsak.

Size bağlı hafıza olsaydı, o zaman çoklu yardımcı olmaz.

I / O bağımlı olduğundan beri, yumurtlamak için kaç konuları sergiyi biraz zordur. Tüm iş öğeleri yaklaşık çok düşük varyans ile işlemek için aynı zaman varsa, bir iş öğesi ne kadar sürer ölçerek yumurtlamak için kaç konuları tahmin edebilirsiniz. Ağ paketlerinin son derece değişken gecikmeleri sahip olma eğilimindedir beri Ancak, bu durum pek mümkün değildir.

Eğer havuzda ücretsiz bir iplik varsa görmek, her öğe işlemek için daha sonra iş parçacığı bir sürü oluşturmak, ve - bir seçenek parçacığı havuzu kullanmaktır. Orada ise, iplik işi gerçekleştirmek o var ve bir sonraki öğenin üzerine taşımak. Aksi takdirde, mevcut olmak için bir iş parçacığı için bekleyin. Çok büyük ve gereksiz bağlam anahtarlarının yaparak zaman kaybediyoruz - parçacığı havuzu boyutu seçimi önemlidir. Çok az ve çok sık dişleri için bekliyorlar.

Yine başka bir seçenek çoklu / çoklu işlem terk ve sadece asenkron I / O onun yerine yapmaktır. Eğer bir tek çekirdekli işlemci üzerinde çalışıyoruz belirtilen yana, bu muhtemelen en hızlı seçenek olacaktır. Eğer bir soket mevcut veri olup olmadığını test etmek socket_select() gibi işlevleri kullanabilirsiniz. Eğer varsa, size verileri okuyabilir, aksi takdirde farklı bir soket üzerine taşımak. Bu çok daha fazla muhasebe yapmak gerekir, ancak verileri farklı bir soket mevcut olduğunda veri Bir sokete gelip bekleyen kaçının.

Eğer konuları ve asenkron I / O kaçınmak ve çoklu sopa istiyorsanız öğe başına işlem yeterince pahalı ise, hala değerli olabilir. Sen o zaman gibi iş bölümü yapabilir:

$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

Bu olacak, kullanıcı başına hangi may yine de istediğini olacak.