Pthreads Çevirisini kullanarak PHP'de çok iş parçacıklı programlama. PHP'de çok iş parçacıklı bilgi işlem: pthreads Jedi Yolu - PCNTL uzantısını kullanarak

Yakın zamanda pthreads'i denedim ve hoş bir sürpriz oldu; bu, PHP'ye birden fazla gerçek iş parçacığıyla çalışma yeteneği ekleyen bir uzantıdır. Öykünme yok, sihir yok, sahte yok; her şey gerçek.



Böyle bir görevi düşünüyorum. Hızlı bir şekilde tamamlanması gereken bir görev havuzu var. PHP'nin bu sorunu çözmek için başka araçları da var, burada bahsedilmiyor, makale pthread'lerle ilgili.



Pthread'ler nedir?

Bu kadar! Yani neredeyse her şey. Aslında meraklı okuyucuyu üzebilecek bir şey var. Bunların hiçbiri varsayılan seçeneklerle derlenmiş standart PHP'de çalışmaz. Çoklu iş parçacığının keyfini çıkarmak için PHP'nizde ZTS'yi (Zend Thread Safety) etkinleştirmiş olmanız gerekir.

PHP kurulumu

Sonra, ZTS ile PHP. ZTS'siz PHP ile karşılaştırıldığında yürütme süresinde bu kadar büyük bir farka dikkat etmeyin (37,65 vs 265,05 saniye), bunu ortak bir paydaya indirmeye çalışmadım PHP ayarları. ZTS'nin olmadığı durumda, örneğin XDebug'u etkinleştirdim.


Gördüğünüz gibi, 2 iş parçacığı kullanıldığında programın yürütme hızı doğrusal koda göre yaklaşık 1,5 kat daha yüksektir. 4 iş parçacığı kullanıldığında - 3 kez.


İşlemci 8 çekirdekli olmasına rağmen, 4'ten fazla iş parçacığı kullanıldığında programın yürütme süresinin neredeyse değişmeden kaldığını not edebilirsiniz. Görünüşe göre bu, işlemcimin 4 fiziksel çekirdeğe sahip olmasından kaynaklanıyor, netlik sağlamak için plakayı bir diyagram şeklinde gösterdim.


Özet

PHP'de pthreads eklentisini kullanarak çoklu iş parçacığı ile oldukça zarif bir şekilde çalışmak mümkündür. Bu, üretkenlikte gözle görülür bir artış sağlar.

Etiketler: Etiket ekleyin

Bazen, örneğin bir veritabanı tablosundaki değişiklikleri kontrol etmek ve diğerinde değişiklik yapmak gibi birden fazla eylemi aynı anda gerçekleştirmek gerekli olabilir. Üstelik işlemlerden biri (örneğin, değişikliklerin kontrol edilmesi) çok zaman alıyorsa, sıralı yürütmenin kaynak dengelemeyi sağlayamayacağı açıktır.

Bu tür bir sorunu çözmek için programlama çoklu iş parçacığı kullanır; her işlem, tahsis edilmiş miktarda kaynakla birlikte ayrı bir iş parçacığına yerleştirilir ve onun içinde çalışır. Bu yaklaşımla tüm görevler ayrı ayrı ve bağımsız olarak tamamlanacaktır.

Her ne kadar PHP çoklu iş parçacığını desteklemese de, onu taklit etmenin birkaç yöntemi vardır; konuşacağız altında.

1. Komut dosyasının birkaç kopyasını çalıştırma (işlem başına bir kopya)

//woman.php if (!isset($_GET["iş parçacığı"])) ( system("wget ​​http://localhost/woman.php?thread=make_me_happy"); system("wget ​​http: //localhost/woman.php?thread=make_me_rich"); ) elseif ($_GET["thread"] == "make_me_happy") ( make_her_happy(); ) elseif ($_GET["thread"] == "make_me_rich" ) ( find_başka_biri( ; )

Bu betiği parametreler olmadan çalıştırdığımızda, gerekli işlevlerin yürütülmesini başlatan işlem kimlikleriyle ("thread=make_me_happy" ve "thread=make_me_rich") kendisinin iki kopyasını otomatik olarak çalıştırır.

Bu şekilde istenen sonucu elde ederiz - iki işlem aynı anda gerçekleştirilir - ancak bu elbette çoklu iş parçacığı değildir, yalnızca görevleri aynı anda gerçekleştirmek için bir destektir.

2. Jedi'ın Yolu - PCNTL uzantısını kullanma

PCNTL, işlemlerle tam olarak çalışmanıza olanak tanıyan bir uzantıdır. Yönetimin yanı sıra mesaj göndermeyi, durumu kontrol etmeyi ve öncelikleri belirlemeyi de destekler. PCNTL kullanan önceki betiğin görünümü şöyle:

$pid = pcntl_fork(); if ($pid == 0) ( make_her_happy(); ) elseif ($pid > 0) ( $pid2 = pcntl_fork(); if ($pid2 == 0) ( find_another_one(); )) )

Oldukça kafa karıştırıcı görünüyor, hadi satır satır inceleyelim.

İlk satırda, mevcut süreci "çatallıyoruz" (çatal, bir işlemin tüm değişkenlerin değerlerini korurken kopyalanmasıdır), onu paralel çalışan iki sürece (geçerli ve alt) bölüyoruz.

Nerede olduğumuzu anlamak için şu an Bir çocuk veya anne sürecinde pcntl_fork işlevi çocuk için 0'ı ve anne için işlem kimliğini döndürür. Bu nedenle, ikinci satırda $pid'e bakıyoruz, eğer sıfırsa, o zaman çocuk süreçteyiz - işlevi yürütüyoruz, aksi takdirde annedeyiz (satır 4), sonra başka bir süreç yaratıyoruz ve benzer şekilde görevi gerçekleştirin.

Komut dosyası yürütme süreci:

Böylece betik, kendi kopyası olan ve benzer değerlere sahip aynı değişkenleri içeren 2 alt süreç daha oluşturur. Ve pcntl_fork fonksiyonunun döndürdüğü tanımlayıcıyı kullanarak o anda hangi thread'de olduğumuzu öğrenip gerekli işlemleri gerçekleştiriyoruz.

Anlaşılan, PHP geliştiricileri paralellik nadiren kullanılır. Senkronize kodun basitliğinden bahsetmeyeceğim; tek iş parçacıklı programlama elbette daha basit ve daha anlaşılırdır, ancak bazen paralelliğin biraz kullanılması performansta gözle görülür bir artış sağlayabilir.

Bu yazıda, pthreads uzantısını kullanarak PHP'de çoklu iş parçacığının nasıl sağlanabileceğine bir göz atacağız. Bunu yapmak için PHP 7.x'in ZTS (Zend Thread Safety) sürümünün yüklü olması gerekir. yüklü uzantı pthreads v3. (PHP 7.1'in yazıldığı sırada, kullanıcıların pthreads deposundaki ana daldan yükleme yapmaları gerekecek - üçüncü taraf uzantısına bakın.)

Küçük bir açıklama: pthreads v2, PHP 5.x için tasarlanmıştır ve artık desteklenmemektedir, pthreads v3, PHP 7.x içindir ve aktif olarak geliştirilmektedir.

Bu kadar uzun bir aradan sonra hemen asıl konuya geçelim!

Bir kerelik görevleri işleme

Bazen tek seferlik görevleri çok iş parçacıklı bir şekilde işlemek isteyebilirsiniz (örneğin, bazı G/Ç bağlantılı görevleri yürütmek). Bu gibi durumlarda, yeni bir iş parçacığı oluşturmak ve bazı işlemleri ayrı bir iş parçacığında çalıştırmak için Thread sınıfını kullanabilirsiniz.

Örneğin:

$görev = yeni sınıf Konuyu genişletiyor ( özel $yanıt; genel işlev run() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $içerik, $eşleşmeler); $this->yanıt = $eşleşmeler; ) ); $görev->başlangıç() && $görev->join(); var_dump($görev->yanıt); // string (6) "Google"

Burada run yöntemi, yeni bir iş parçacığının içinde yürütülecek olan işlemimizdir. Thread::start çağrıldığında yeni bir iş parçacığı oluşturulur ve run yöntemi çağrılır. Daha sonra alt iş parçacığının yürütülmesi bitene kadar engellenecek olan Thread::join'i çağırarak alt iş parçacığını ana iş parçacığına geri bağlarız. Bu, sonucu yazdırmayı denemeden önce görevin yürütülmesinin tamamlanmasını sağlar (bu, $task->response'da saklanır).

Bir sınıfı akış mantığıyla ilişkili ek sorumluluklarla (bir çalıştırma yöntemi tanımlama sorumluluğu dahil) kirletmek istenmeyebilir. Bu tür sınıfları Threaded sınıfından miras alarak ayırt edebiliriz. Daha sonra başka bir iş parçacığının içinde çalıştırılabilirler:

Sınıf Görevi, İş Parçacığı'nı genişletir ( public $response; public function someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->yanıt = $eşleşir; ) ) $görev = yeni Görev; $iş parçacığı = yeni sınıf($görev) Konuyu genişletir ( özel $görev; public function __construct(Threaded $görev) ( $this->görev = $görev; ) public function run() ( $this->task->someWork( ) ); $thread->start() && $thread->join(); var_dump($görev->yanıt);

Ayrı bir iş parçacığında çalıştırılması gereken herhangi bir sınıf mutlak Threaded sınıfından miras alır. Bunun nedeni, farklı iş parçacıklarında işlem gerçekleştirmek için gerekli yeteneklerin yanı sıra örtülü güvenlik ve kullanışlı arayüzler (kaynak senkronizasyonu gibi) sağlamasıdır.

pthreads uzantısının sunduğu sınıf hiyerarşisine bir göz atalım:

İş Parçacığı (Geçilebilir, Toplanabilir uygular) İş Parçacığı Çalışanı Uçucu Havuzu

Thread ve Threaded sınıflarının temellerini zaten ele aldık ve öğrendik, şimdi diğer üçüne (Worker, Volatile ve Pool) bir göz atalım.

Konuları Yeniden Kullanma

Paralelleştirilmesi gereken her görev için yeni bir iş parçacığı başlatmak oldukça pahalıdır. Bunun nedeni, PHP'de çoklu iş parçacıklarını elde etmek için pthreads'lerde ortak-hiçbir mimarinin uygulanması gerekmesidir. Bu, PHP yorumlayıcısının geçerli örneğinin tüm yürütme içeriğinin (her sınıf, arayüz, özellik ve işlev dahil) oluşturulan her iş parçacığı için kopyalanması gerektiği anlamına gelir. Bunun performansta gözle görülür bir etkisi olduğundan, akışın mümkün olduğunca her zaman yeniden kullanılması gerekir. İş parçacıkları iki şekilde yeniden kullanılabilir: İşçileri kullanarak veya Havuzları kullanarak.

Worker sınıfı, başka bir iş parçacığı içinde bir dizi görevi eşzamanlı olarak gerçekleştirmek için kullanılır. Bu, yeni bir Worker örneği oluşturarak (yeni bir iş parçacığı oluşturur) ve ardından görevleri bu ayrı iş parçacığının yığınına (Worker::stack kullanarak) aktararak yapılır.

İşte küçük bir örnek:

Sınıf Görevi, Dişli ( özel $değer; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Görev: ($this->value)'yi genişletir \n"; )) $işçi = yeni İşçi(); $işçi->başlat(); for ($i = 0; $i stack(new Task($i)); ) while ($worker->collect()); $işçi->kapatma();

Yukarıdaki örnekte, yeni bir $worker nesnesi için 15 görev Worker::stack yöntemi aracılığıyla yığına aktarılır ve daha sonra aktarıldıkları sıraya göre işlenirler. Yukarıda gösterildiği gibi Worker::collect yöntemi, görevlerin yürütülmesi biter bitmez temizlemek için kullanılır. Bununla birlikte, bir while döngüsü içinde, Worker::shutdown çağırmadan önce yığındaki tüm görevler tamamlanıp temizlenene kadar ana iş parçacığını bloke ederiz. Bir işçiyi erken sonlandırmak (yani hala tamamlanması gereken görevler varken), tüm görevlerin yürütülmesini tamamlayana kadar ana iş parçacığını yine de engelleyecektir, yalnızca görevler çöp olarak toplanmayacaktır (bu, temsil edilen bellek sızıntılarını gerektirir).

Worker sınıfı, görev yığınıyla ilgili diğer birkaç yöntemi sağlar; bunlar arasında son yığılmış görevi kaldırmak için Worker::unstack ve yürütme yığınındaki görev sayısını almak için Worker::getStacked bulunur. Bir işçi yığını yalnızca yürütülmesi gereken görevleri içerir. Yığındaki bir görev tamamlandığında kaldırılır ve çöp toplama için ayrı bir (dahili) yığına yerleştirilir (Worker::collect yöntemi kullanılarak).

Bir iş parçacığını birden çok görevde yeniden kullanmanın başka bir yolu da iş parçacığı havuzu kullanmaktır (Pool sınıfı aracılığıyla). Bir iş parçacığı havuzu, görevlerin yürütülmesini sağlamak için bir grup Çalışanı kullanır eşzamanlı havuz oluşturulduğunda eşzamanlılık faktörünün (birlikte çalıştığı havuz iş parçacığı sayısı) ayarlandığı .

Yukarıdaki örneği bir çalışan havuzunu kullanacak şekilde uyarlayalım:

Sınıf Görevi, Dişli ( özel $değer; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Görev: ($this->value)'yi genişletir \n"; )) $havuz = yeni Havuz(4); for ($i = 0; $i submit(new Task($i)); ) while ($pool->collect()); $havuz->kapatma();

Havuz kullanımında işçi kullanımıyla karşılaştırıldığında birkaç dikkate değer fark vardır. Birincisi, havuzun manuel olarak başlatılmasına gerek yoktur; görevleri kullanılabilir hale gelir gelmez yürütmeye başlar. İkincisi, biz Göndermek havuza yönelik görevler değil onları bir yığına koy. Ek olarak, Pool sınıfı Threaded'den miras almaz ve bu nedenle diğer thread'lere (Worker'ın aksine) aktarılamaz.

Nasıl İyi pratikÇalışanlar ve havuzlar için, her zaman görevlerini tamamlar tamamlamaz temizlemeli ve ardından manuel olarak sonlandırmalısınız. Thread sınıfı kullanılarak oluşturulan iş parçacıklarının da üst iş parçacığına eklenmesi gerekir.

pthread'ler ve (değişmez) değişkenlik

Değineceğimiz son sınıf, pthreads v3'e yeni eklenen Volatile sınıfıdır. Değişmezlik pthread'lerde önemli bir kavram haline geldi çünkü onsuz performans önemli ölçüde zarar görüyor. Bu nedenle, varsayılan olarak, kendileri de Threaded nesneler olan Threaded sınıflarının özellikleri artık değişmezdir ve bu nedenle, ilk atamalarından sonra bunların üzerine yazılamaz. Bu tür özellikler için açık değiştirilebilirlik şu anda tercih edilmektedir ve yeni Volatile sınıfı kullanılarak hala elde edilebilmektedir.

Yeni değişmezlik kısıtlamalarını gösterecek bir örneğe bakalım:

Sınıf Görevi, Dişli // Dişli bir sınıfı genişletir ( public function __construct() ( $this->data = new Threaded(); // $this->data, bir Dişli sınıfın Dişli özelliği olduğundan üzerine yazılamaz) ) $task = new class(new Task()) Thread'i genişletir ( // bir Threaded sınıfı, çünkü Thread, Threaded public function'ı genişletir __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> data); // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // özellik bir Threaded sınıfının Threaded üyesi olduğundan geçersiz ) );

Uçucu sınıfların iş parçacıklı özellikleri ise değiştirilebilir:

Sınıf Görevi Uçucuyu genişletir ( public function __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // geçerli, çünkü geçici bir sınıftayız ) ) $task = new class(new Task()) Thread'i genişletir ( public function __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // Volatile Threaded'i genişlettiği için hala geçersiz, yani özellik hala Threaded sınıfının Threaded üyesidir $this->volatileMember = new StdClass() );

Volatile sınıfının, Threaded özelliklerini (unset()'in yanı sıra) değiştirme yeteneğini sağlamak için ana Threaded sınıfı tarafından empoze edilen değişmezliği geçersiz kıldığını görebiliriz.

Değişkenlik ve Uçucu sınıf dizileri konusunu kapsayan başka bir tartışma konusu daha vardır. Pthread'lerde diziler, Threaded sınıfının bir özelliğine atandıklarında otomatik olarak Volatile nesnelerine dönüştürülür. Bunun nedeni, birden çok PHP bağlamı dizisini değiştirmenin güvenli olmamasıdır.

Bazı şeyleri daha iyi anlamak için tekrar bir örneğe bakalım:

$dizi = ; $görev = yeni sınıf($array) Thread'i genişletir ( özel $veri; public function __construct(array $array) ( $this->data = $array; ) public function run() ( $this->veri = 4; $ this->veri = 5; print_r($this->veri) ); $görev->başlat() && $görev->join(); /* Çıktı: Uçucu Nesne ( => 1 => 2 => 3 => 4 => 5) */

Uçucu nesnelerin (yukarıda gösterildiği gibi) subset() operatörü gibi dizi işlemlerini destekledikleri için dizilermiş gibi ele alınabileceğini görüyoruz. Ancak Uçucu sınıflar array_pop ve array_shift gibi temel dizi işlevlerini desteklemez. Bunun yerine Threaded sınıfı bize yerleşik yöntemler gibi işlemler sağlar.

Bir gösteri olarak:

$veri = yeni sınıf, Uçucuyu genişletiyor ( public $a = 1; public $b = 2; public $c = 3; ); var_dump($veri); var_dump($data->pop()); var_dump($data->shift()); var_dump($veri); /* Çıktı: object(sınıf@anonim)#1 (3) ( ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ) int(3) int(1) object(sınıf@anonim)#1 (1) ( ["b"]=> int(2) ) */

Desteklenen diğer işlemler arasında Threaded::chunk ve Threaded::merge bulunur.

Senkronizasyon

Bu makalenin son bölümünde pthreads'te senkronizasyona bakacağız. Senkronizasyon, paylaşılan kaynaklara erişimi kontrol etmenize olanak tanıyan bir yöntemdir.

Örneğin basit bir sayaç uygulayalım:

$counter = yeni sınıf Konuyu genişletir ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $sayaç->başlat(); for ($i = 0; $i i; ) $counter->join(); var_dump($sayaç->i); // 10'dan 20'ye kadar bir sayı yazdıracağız

Senkronizasyon kullanılmadan çıktı deterministik değildir. Birden fazla iş parçacığı, kontrollü erişim olmadan aynı değişkene yazar; bu, güncellemelerin kaybolacağı anlamına gelir.

Zamanlama ekleyerek doğru çıktıyı 20 elde edecek şekilde bunu düzeltelim:

$counter = yeni sınıf Konuyu genişletir ( public $i = 0; public function run() ( $this->synchronized(function () ( for ($i = 0; $i i; ) )); ) ); $sayaç->başlat(); $counter->synchronized(function ($counter) ( for ($i = 0; $i i; ) ), $counter); $counter->join(); var_dump($sayaç->i); // int(20)

Senkronize kod blokları ayrıca Threaded::wait ve Threaded::notify (veya Threaded::notifyAll) yöntemlerini kullanarak birbirleriyle iletişim kurabilir.

İki senkronize while döngüsünde alternatif bir artış:

$counter = yeni sınıf Konuyu genişletir ( public $cond = 1; public function run() ( $this->synchronized(function () ( for ($i = 0; $i notify(); if ($this->cond) === 1) ( $this->koşul = 2; $this->bekle(); ) ) ) ); $sayaç->başlat(); $counter->synchronized(function ($counter) ( if ($counter->cond !== 2) ( $counter->wait(); // önce diğerinin başlamasını bekleyin ) for ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ), $counter); $counter->join(); /* Çıktı: int(0) int(10) int(1) int(11) int(2) int(12) int(3) int(13) int(4) int(14) int(5) int( 15) int(6) int(16) int(7) int(17) int(8) int(18) int(9) int(19) */

Threaded::wait çağrısının etrafına yerleştirilen ek koşulları fark edebilirsiniz. Bu koşullar kritiktir çünkü senkronize geri aramanın bir bildirim aldığında ve belirtilen koşul doğru olduğunda devam etmesine izin verirler. Bu önemlidir çünkü bildirimler Threaded::notify çağrıldığı zaman dışındaki yerlerden de gelebilir. Bu nedenle, eğer Threaded::wait yöntemine yapılan çağrılar koşulların içine alınmadıysa, çalıştıracağız. yanlış uyandırma çağrılarıöngörülemeyen kod davranışına yol açacaktır.

Çözüm

pthreads paketinin beş sınıfına (Threaded, Thread, Worker, Volatile ve Pool) ve her sınıfın nasıl kullanıldığına baktık. Ayrıca pthread'lerdeki yeni değişmezlik kavramına da göz attık ve desteklenen senkronizasyon yeteneklerine kısa bir genel bakış sunduk. Bu temel bilgiler yerine getirildikten sonra artık pthread'lerin gerçek dünyadaki durumlarda nasıl kullanılabileceğine bakmaya başlayabiliriz! Bir sonraki yazımızın konusu bu olacak.

Bir sonraki gönderinin çevirisiyle ilgileniyorsanız bana bildirin: sosyal medyada yorum yapın. ağlar, olumlu oy verin ve gönderiyi meslektaşlarınız ve arkadaşlarınızla paylaşın.

  • Programlama,
  • Paralel programlama
  • Yakın zamanda pthreads'i denedim ve hoş bir sürpriz oldu; bu, PHP'ye birden fazla gerçek iş parçacığıyla çalışma yeteneği ekleyen bir uzantıdır. Öykünme yok, sihir yok, sahte yok; her şey gerçek.



    Böyle bir görevi düşünüyorum. Hızlı bir şekilde tamamlanması gereken bir görev havuzu var. PHP'nin bu sorunu çözmek için başka araçları da var, burada bahsedilmiyor, makale pthread'lerle ilgili.



    Pthread'ler nedir?

    Bu kadar! Yani neredeyse her şey. Aslında meraklı okuyucuyu üzebilecek bir şey var. Bunların hiçbiri varsayılan seçeneklerle derlenmiş standart PHP'de çalışmaz. Çoklu iş parçacığının keyfini çıkarmak için PHP'nizde ZTS'yi (Zend Thread Safety) etkinleştirmiş olmanız gerekir.

    PHP kurulumu

    Sonra, ZTS ile PHP. ZTS'siz PHP ile karşılaştırıldığında yürütme süresindeki büyük farka aldırış etmeyin (37.65 vs 265.05 saniye), PHP kurulumunu genelleştirmeye çalışmadım. ZTS'nin olmadığı durumda, örneğin XDebug'u etkinleştirdim.


    Gördüğünüz gibi, 2 iş parçacığı kullanıldığında programın yürütme hızı doğrusal koda göre yaklaşık 1,5 kat daha yüksektir. 4 iş parçacığı kullanıldığında - 3 kez.


    İşlemci 8 çekirdekli olmasına rağmen, 4'ten fazla iş parçacığı kullanıldığında programın yürütme süresinin neredeyse değişmeden kaldığını not edebilirsiniz. Görünüşe göre bu, işlemcimin 4 fiziksel çekirdeğe sahip olmasından kaynaklanıyor, netlik sağlamak için plakayı bir diyagram şeklinde gösterdim.


    Özet

    PHP'de pthreads eklentisini kullanarak çoklu iş parçacığı ile oldukça zarif bir şekilde çalışmak mümkündür. Bu, üretkenlikte gözle görülür bir artış sağlar.

    Etiketler:

    • php
    • pthread'ler
    Etiket ekle

    Yakın zamanda pthreads'i denedim ve hoş bir sürpriz oldu; bu, PHP'ye birden fazla gerçek iş parçacığıyla çalışma yeteneği ekleyen bir uzantıdır. Öykünme yok, sihir yok, sahte yok; her şey gerçek.



    Böyle bir görevi düşünüyorum. Hızlı bir şekilde tamamlanması gereken bir görev havuzu var. PHP'nin bu sorunu çözmek için başka araçları da var, burada bahsedilmiyor, makale pthread'lerle ilgili.



    Pthread'ler nedir?

    Bu kadar! Yani neredeyse her şey. Aslında meraklı okuyucuyu üzebilecek bir şey var. Bunların hiçbiri varsayılan seçeneklerle derlenmiş standart PHP'de çalışmaz. Çoklu iş parçacığının keyfini çıkarmak için PHP'nizde ZTS'yi (Zend Thread Safety) etkinleştirmiş olmanız gerekir.

    PHP kurulumu

    Sonra, ZTS ile PHP. ZTS'siz PHP ile karşılaştırıldığında yürütme süresindeki büyük farka aldırış etmeyin (37.65 vs 265.05 saniye), PHP kurulumunu genelleştirmeye çalışmadım. ZTS'nin olmadığı durumda, örneğin XDebug'u etkinleştirdim.


    Gördüğünüz gibi, 2 iş parçacığı kullanıldığında programın yürütme hızı doğrusal koda göre yaklaşık 1,5 kat daha yüksektir. 4 iş parçacığı kullanıldığında - 3 kez.


    İşlemci 8 çekirdekli olmasına rağmen, 4'ten fazla iş parçacığı kullanıldığında programın yürütme süresinin neredeyse değişmeden kaldığını not edebilirsiniz. Görünüşe göre bu, işlemcimin 4 fiziksel çekirdeğe sahip olmasından kaynaklanıyor, netlik sağlamak için plakayı bir diyagram şeklinde gösterdim.


    Özet

    PHP'de pthreads eklentisini kullanarak çoklu iş parçacığı ile oldukça zarif bir şekilde çalışmak mümkündür. Bu, üretkenlikte gözle görülür bir artış sağlar.



    
    Tepe