Neden daha fazla iş parçacığı kullanmak daha az iş parçacığı kullanmaktan daha yavaş yapıyor


30

8 iş parçacığı kullanarak X programını çalıştırmayı denedim ve n dakika içinde sona erdi . 50 iplik
kullanarak aynı programı çalıştırmaya çalıştım ve n * 10 dakika içinde bitmişti .

Bu neden oluyor ve kullanabileceğim en iyi iş parçacığı sayısını nasıl alabilirim?

Yanıtlar:


33

Bu sorduğunuz karmaşık bir soru. Dişlerinin yapısı hakkında daha fazla şey bilmeden söylemek zor. Sistem performansını teşhis ederken dikkate alınması gereken bazı şeyler:

İşlem / iş parçacığı mı

  • CPU'ya bağlı (çok fazla CPU kaynağı gerektiriyor)
  • Bellek bağlı (çok sayıda RAM kaynağına ihtiyaç duyar)
  • G / Ç sınırı (Ağ ve / veya sabit sürücü kaynakları)

Bu üç kaynağın tümü sonludur ve herhangi biri sistemin performansını sınırlayabilir. Özel durumunuzun hangi (2 veya 3 olabileceği) tüketeceğine bakmanız gerekir.

Sen kullanabilirsiniz ntopve iostatve vmstatne olup bittiğini teşhis etmek.


8
Donanım da önemli. Fiziksel, sanal, çekirdek sayısı, çekirdek tipi, L1 / L2 / L3 önbellek vb.
EightBitTony

46

“Bu neden oluyor?” cevaplaması kolay bir şey. Dört kişiyi yan yana yerleştirebileceğiniz bir koridorunuz olduğunu hayal edin. Tüm çöpleri bir ucundan diğer ucuna taşımak istiyorsun. En verimli insan sayısı 4'tür.

Eğer 1-3 kişiniz varsa, o zaman bazı koridor alanlarını kullanmaktan mahrum kalacaksınız. 5 veya daha fazla kişiniz varsa, o zaman bu kişilerden en az biri temelde sürekli başka bir kişinin kuyruğunda kalmış durumda kalır. Gittikçe daha fazla insan eklemek sadece koridoru tıkamaktadır, bu da etkinliği hızlandırmaz.

Demek sıraya girmeden sığabileceğin kadar insanın olmasını istiyorsun. Neden kuyruğa aldığınız (veya tıkanıklıklar) slm'ın cevabındaki sorulara bağlıdır.


1
Örneğin yanıltıcı. Şunu söylemek daha iyi olurdu: "Dört kişiyi yan yana koyabileceğiniz bir koridorunuz var, yan yana ve siz ve diğer insanlar tarafından farklı işler için kullanılıyor. Koridordan kimlerin geçebileceğine karar veren bir hakem var. O zaman en verimli insan sayısı 4'ten büyük ve bazı rakamlardan daha az. Genellikle, bazı işlemcilerin CPU sayısından daha fazla olması, tam olarak 4 iş parçacığı kullanmaktan daha iyi performans gösterir . Eğer varsa sadece CPU kullanan bir, daha sonra 4iyi bir sayıdır.
Bakuriu,

7
Harika bir örnek, +1. Bakuriu, sınırlı bir paylaşılan kaynağın sorununu gösteren bir örnek. En iyi iş parçacığı sayısını bulmak için değil, sorunu açıklıyor.
Bananguin

1
Ayrıca, dişlerin hala devam eden kendi içerik bağlamı anahtarlamalarına sahip olduğunu akılda tutmak yararlı olacaktır. Diş sayısının arttırılması, performans kapasitesini arttırmaz (sizin de belirttiğiniz gibi), fakat çekirdeğe daha fazla iş yapmasıyla CPU süresini de azaltır. Temel olarak, diş açmada azalan geri dönüşler var ve çok fazla şey yapmak performansın geri dönüşüne neden oluyor.
Bratchley

9
Her problem birçok karmaşıklık seviyesinde tanımlanabilir. Temel konuların açıklanmasının faydalı olduğunu düşündüğüm problemin bir yaklaşımını teklif ettim. Elbette daha rafine ve daha ayrıntılı olabilir, ancak ne kadar ayrıntılı yaparsanız, konuya giriş yapmak o kadar az işe yarar.
EightBitTony

En uygun iş parçacığı sayısını hesaplamak için çok zaman harcamak yerine, kolayca değiştirilebilmesi için kod eklerdim. Bunun gibi herhangi bir büyük birleştirme, kusursuz olması için sayısız test çalıştırması (verilerinizin küçük alt kümeleriyle birlikte) gerektirir. Performansta büyük bir düşüş görene ya da diğer sistem etkinlikleri üzerinde etkisi kabul edilemez olana kadar iş parçacığı sayısını artırın.
DocSalvager

20

Yaygın bir öneri n + 1 ipliktir, n mevcut CPU çekirdeği sayısıdır. Bu şekilde n thread, 1 thread disk I / O için beklerken CPU'yu çalıştırabilir. Daha az sayıda iş parçacığı olması CPU kaynağını tam olarak kullanmayacak (bir noktada beklemek için her zaman G / Ç olacaktır), daha fazla iş parçacığı olması iş parçacığı CPU kaynağı üzerinde kavgaya neden olacaktır.

İplikler serbest değil, baş üstü gibi bağlam anahtarları ile birlikte gelir ve - eğer genellikle durum olan dişler arasında veri alışverişi yapılması gerekiyorsa - çeşitli kilitleme mekanizmaları. Bu, yalnızca kodu çalıştırmak için gerçekten daha fazla CPU çekirdeğine sahip olduğunuzda maliyeti düşürür. Tek çekirdekli bir işlemcide, tek bir işlem (ayrı iş parçacığı yok) genellikle yapılan herhangi bir iş parçacığından daha hızlıdır. İş parçacıkları sihirli bir şekilde işlemcinizi daha hızlı çalıştırmaz, bu sadece ekstra çalışma anlamına gelir.


Bu, mevcut bilgi miktarı verilen genel cevap olmalıdır. diğer cevaplar gibi tam bir tez ve felsefe ihtiyacımız yok
Allahjane

9

Diğerlerinin de belirttiği gibi ( slm cevap , EightBitTony cevap ) bu karmaşık bir sorudur ve daha fazlası, çünkü ne yaptığınızı ve nasıl yaptıklarını açıklamadığınızdan.

Ancak kesin olarak daha fazla dişe atmak işleri daha da kötüleştirebilir.

Paralel hesaplama alanında, uygulanabilecek Amdahl yasası var (ya da yapamazsınız, ancak problemin ayrıntılarını tanımlamazsınız, bu yüzden ...) ve bu problem sınıfı hakkında bazı genel bilgiler verebilir.

Amdahl yasasının amacı, herhangi bir programda (herhangi bir algoritmada) her zaman paralel olarak çalıştırılamayan bir yüzde ( sıralı kısım ) olduğu ve paralel olarak çalıştırılabilecek başka bir yüzde olduğu ( paralel kısım ) [Açıkçası bu iki bölüm% 100'e kadar ekler].

Bu bölümler yürütme süresinin yüzdesi olarak ifade edilebilir. Örneğin, tamamen ardışık işlemlerde harcanan zamanın% 25'i olabilir ve kalan% 75'lik bir süre paralel olarak gerçekleştirilebilecek olan operasyonda harcanır.

Wikipedia'dan görüntü ( Wikipedia'dan görüntü )

Amdahl kanunu, bir programın verilen her paralel kısmı (örneğin% 75) için, işi yapmak için daha fazla işlemci kullanıyor olsanız bile, uygulamayı şu ana kadar (örneğin en fazla 4 kez) hızlandırabileceğinizi öngörmektedir.

Genel bir kural olarak, paralel yürütmede dönüştüremediğiniz program ne kadar çok olursa, daha fazla yürütme birimi (işlemci) kullanarak daha az elde edersiniz.

İş parçacığı kullanıyorsanız (ve fiziksel işlemcileri değil) durum bundan daha da kötü olabilir. Konuların aynı fiziksel işlemciyi / çekirdeği (başka bir cevapta belirtildiği gibi paylaşan bir çoklu görev şeklidir ) paylaşan işlenebileceğini (mevcut uygulamaya ve donanıma bağlı olarak, örneğin CPU'lar / Çekirdekler ) unutmayın.

Bu teorik tahmin (CPU zamanları hakkında) diğerlerinin pratik darboğazlarını dikkate almaz

  1. Sınırlı I / O hızı (sabit disk ve ağ "hız")
  2. Bellek boyutu sınırları
  3. Diğerleri

pratik uygulamalarda kolayca sınırlayıcı faktör olabilir.


Bu cevap seçilmelidir.
Eonil

6

Buradaki suçlu "CONTEXT SWITCHING" olmalıdır. Başka bir iş parçacığı çalıştırmaya başlamak için geçerli iş parçacığının durumunu kaydetme işlemidir. Bir dizi dişe aynı önceliğe sahip olması durumunda, yürütmeyi bitirene kadar çevrilmeleri gerekir.

Sizin durumunuzda, 50 iş parçacığı olduğunda, sadece 10 iş parçacığı çalıştırmaya kıyasla çok sayıda bağlam değişimi gerçekleşir.

Bağlam geçişi nedeniyle ortaya çıkan genel masraf, programınızın yavaş çalışmasına neden olan şeydir


İpliklerin ne olduğunu bilmediğimizden, bu bir tahmin gibi görünüyor. Evet, içerik değiştirme bir ek yük getirir, ancak iş parçacığı bir tür veri analizi yapıyorsa, sorun önbellek sorunları olabilir (yani iş parçacığını değiştirdiğinizde her zaman temizlemeniz gerektiğinden önbelleği kullanamamak).
EightBitTony

Çok sayıda bağlam anahtarıyla ilgilenmediğimiz sürece, iş parçacığı bağlamının kendi içinde geçişi , büyük olasılıkla performans üzerinde büyük bir düzen etkisi yaratmayacaktır. 50 iş parçacığı yüksek ama aşırı değil (şu an benim kutumda ps ax | wc -l225 işlem bildiriyor ve hiçbir şekilde ağır yüklü değil). @ EightBitTony'nin tahminde bulunma eğilimindeyim; önbellek geçersiz kılma büyük olasılıkla daha büyük bir sorundur, çünkü önbelleği her yıkadığınızda, CPU eons'u RAM'den gelen kod ve veriler için beklemelidir .
CVn

3

EightBitTony'nin metaforunu düzeltmek için:

“Bu neden oluyor?” cevaplaması kolay bir şey. Biri dolu diğeri boş olan iki yüzme havuzunuz olduğunu hayal edin . Tüm suyu birinden diğerine taşımak istiyorsunuz ve 4 kovaya sahip olmak istiyorsunuz . En verimli insan sayısı 4'tür.

Eğer 1-3 kişiniz varsa, o zaman bazı kovaları kullanmaktan mahrum kalacaksınız . 5 veya daha fazla kişiniz varsa, o zaman bu kişilerden en az biri bir kepçe bekliyor . Gittikçe daha fazla insan eklemek ... etkinliği hızlandırmıyor.

Yani aynı anda bazı işleri yapabilen (bir kova kullanın) mümkün olduğunca çok insana sahip olmak istiyorsunuz .

Buradaki bir kişi bir ipliktir ve bir kova, hangi yürütme kaynağının darboğaz olduğunu gösterir. Daha fazla iş parçacığı eklemek, bir şey yapamazlarsa yardımcı olmaz. Ek olarak, bir kepçeyi bir kişiden diğerine geçirmenin, sadece kepçeyi aynı mesafeye taşıyan tek bir kişiden genellikle daha yavaş olduğunu vurgulamalıyız . Diğer bir deyişle, bir çekirdeği açan iki diş tipik olarak iki defa uzun süren tek bir dişten daha az iş başarır: bunun nedeni iki diş arasında geçiş yapmak için yapılan fazladan çalışmadır.

Sınırlayıcı yürütme kaynağının (kova) bir CPU mu yoksa bir çekirdek mi, yoksa amaçlarınız için aşırı dişli bir komut borusu olması mimarinin hangi bölümünün sınırlayıcı faktörünüz olduğuna bağlıdır. Ayrıca, dişlilerin tamamen bağımsız olduğunu varsayıyoruz . Bu paylaştıkları yalnızca durumdur hiçbir veri (ve herhangi bir önbellek çarpışmaları önlemek).

Birkaç kişinin önerdiği gibi, G / Ç için sınırlayıcı kaynak, yararlı bir şekilde sıralanabilir G / Ç işlemlerinin sayısı olabilir: bu, bir dizi donanım ve çekirdek faktörüne bağlı olabilir, ancak bu sayıdan çok daha büyük olabilir çekirdekler. Burada, çalıştırma sınırlı kodla karşılaştırıldığında çok pahalı olan bağlam anahtarı, G / Ç sınırlama koduyla karşılaştırıldığında oldukça ucuzdur. Ne yazık ki, bunu kovalarla haklı çıkarmaya çalışırsam metaforun tamamen kontrolden çıkacağını düşünüyorum.

G / Ç bağlı koduyla en uygun davranışın hala her bir boru hattı / çekirdek / CPU başına en fazla bir iş parçacığına sahip olduğunu unutmayın. Ancak, senkronize olmayan veya senkronize olmayan / bloke edici olmayan G / Ç kodu yazmanız gerekir ve nispeten küçük performans iyileştirmesi her zaman ekstra karmaşıklığı haklı çıkarmaz.


PS. Orijinal koridor metaforuyla ilgili sorunum, 4 sıra insanın olabileceği, 2 sıra çöp taşıyan ve 2 daha fazla toplama yapmak için geri dönecek olmanız gerektiğini şiddetle tavsiye ediyor. Sonra koridor olarak neredeyse sürece her kuyruğu yapabilir ve ekleme insanlar yaptılar algoritma yukarı hızını (temelde bir konveyör bant içine bütün koridorunu döndü).

Aslında bu senaryo, TCP ağındaki gecikme ve pencere boyutu arasındaki ilişkinin standart tanımına çok benzer, bu yüzden bana atladı.


Bu bir metafor değil, sistemi insanlara kolayca görselleştirebilecekleri şekilde açıklamak için tasarlanmış bir yaklaşımdır. Bu nedenle, her zaman bir sonraki ayrıntı seviyesini bilen insanlar tarafından “ovulacak” olacak, ancak ayrıntı seviyelerinin yeni başlayanlar için aslında gerekli olmadığının farkında değilsiniz. Hiç kimse doktora seviyesinden başlayarak parçacık fiziğini öğrenemez. Öncesinde olan her şey, sizi adım adım ilerletmek, gittikçe arıtmak için yönlendirdikleri bir yaklaşımdır. Bu 'yanlış' değil, sadece tam resim değil.
EightBitTony

Hangi konuşmayı kullandığın hakkında hiç kimse karıştı ve kötü bir benzetme olmadı. Her analojinin, tarif etmesi gereken şeyden ayrıldığı ve kullanışlı olmasını bıraktığı şeyin ötesinde bir sınırı vardır. Ben sadece bundan bahsettim, çünkü orijinal bana farklı bir senaryoyu çok kuvvetli bir şekilde hatırlattı ve bu versiyonun (umarım) geliştirilmiş öngörü için daha karmaşık olduğunu düşünmüyorum.
İşe yaramaz

0

Anlaşılması oldukça basit ve basittir. CPU'nuzun desteklediğinden daha fazla iş parçacığına sahip olmak aslında serileştiriyor ve paralelleştirmiyor. Ne kadar çok iş parçacığına sahipseniz, sistem o kadar yavaş olur. Sonuçlarınız aslında bu olgunun bir kanıtı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.