Microsoft'un eşzamansız yaklaşımı , çok iş parçacıklı programlama amaçlarının en yaygın olanı için iyi bir alternatiftir: IO görevlerine göre yanıt verme yeteneğini geliştirmek.
Bununla birlikte, zaman uyumsuz yaklaşımın performansı iyileştirme ya da CPU yoğun görevlere göre yanıt verme yeteneğini geliştirme yeteneğinin olmadığını fark etmek önemlidir.
Duyarlılık için Çoklu Okuma
Duyarlılık için çok iş parçacığı, bir programı ağır GÇ görevleri veya ağır hesaplama görevleri sırasında yanıt veren geleneksel yoldur. Dosyaları bir arka plan iş parçacığına kaydedersiniz, böylece kullanıcı sabit sürücünün görevini tamamlamasını beklemeden çalışmalarına devam edebilir. GÇ ipliği genellikle yazının bir bölümünün bitmesini bekler, bu nedenle bağlam anahtarları sık sık.
Benzer şekilde, karmaşık bir hesaplama yaparken, kullanıcı arabiriminin duyarlı kalmasını sağlamak için düzenli bağlam geçişine izin vermek istiyorsunuz ve kullanıcı programın çökeceğini düşünmüyor.
Buradaki amaç, genel olarak, farklı CPU'larda birden fazla iş parçacığı elde etmektir. Bunun yerine, yalnızca uzun süredir devam eden arka plan görevi ve UI arasında gerçekleşen bağlam anahtarlarının elde edilmesiyle ilgileniyoruz, böylece kullanıcı arabirimi arka plan görevi çalışırken kullanıcıyı güncelleyebilir ve yanıt verebilir. Genel olarak, kullanıcı arayüzü çok fazla CPU gücü kullanmaz ve iş parçacığı çerçevesi veya işletim sistemi genellikle onları aynı CPU'da çalıştırmaya karar verir.
Aslında bağlamsal anahtarlama maliyeti nedeniyle toplam performansı kaybediyoruz, ancak işlemcinin performansı bizim hedefimiz olmadığı için umursamıyoruz. Genelde ihtiyaç duyduğumuzdan daha fazla CPU gücüne sahip olduğumuzu biliyoruz ve bu yüzden çoklu okuma ile ilgili hedefimiz, kullanıcının zamanını boşa harcamamaksızın kullanıcı için bir görev yapmak.
"Asenkron" Alternatif
"Eşzamansız yaklaşım", bu resmi tek bir iş parçacığı içindeki bağlam anahtarları etkinleştirerek değiştirir. Bu, tüm görevlerimizin tek bir CPU üzerinde çalışacağını garanti eder ve daha az diş açma / temizleme ve dişler arasında daha az gerçek bağlam geçişi açısından mütevazı performans iyileştirmeleri sağlayabilir.
Bir ağ kaynağının alınmasını beklemek için yeni bir iş parçacığı oluşturmak yerine (örneğin, bir görüntüyü indirmek), görüntünün async
kullanılabilir await
hale geldiği ve bu arada çağıran yönteme yol açan bir yöntem kullanılır.
Buradaki ana avantaj, kilitleri ve senkronizasyonu hiç kullanmadığınız için kilitlenmeden kaçınma gibi konularla ilgili endişelenmenize gerek kalmaması ve programcının arka plan iş parçacığını ayarlama ve geri alma konusunda biraz daha az iş olması. UI güvenli bir şekilde güncellemek için sonuç geri geldiğinde UI iş parçacığında.
Teknik ayrıntılara çok fazla bakmadım ama izlenimim, zaman zaman hafif CPU etkinliği ile indirmeyi yönetmek, ayrı bir iş parçacığı için değil, UI etkinlik kuyruğundaki bir görev gibi, ve daha sonra indirme işlemi tamamlandığında, zaman uyumsuz yöntem bu olay kuyruğundan devam eder. Başka bir deyişle, await
"ihtiyacım olan sonucun mevcut olup olmadığını kontrol et, beni bu konunun görev sırasına koyup koymadığını" söyleyen bir şey anlamına geliyor.
Bu yaklaşımın CPU yoğun bir görevin sorununu çözmeyeceğini unutmayın: bekleyecek bir veri yok, bu nedenle gerçek bir arka plan çalışan iş parçacığı oluşturmadan gerçekleşmesi gereken bağlam anahtarlarını alamıyoruz. Tabii ki, arka plan iş parçacığını başlatmak ve sonucu asenkron yaklaşımı kullanan bir programda, arka plan iş parçacığını başlatmak ve sonucu döndürmek için eşzamansız bir yöntem kullanmak yine de uygun olabilir.
Performans için Çoklu Okuma
“Performans” hakkında konuştuğunuz için, çoklu iş görmenin performans kazanımları için nasıl kullanılabileceğini tartışmak isterim, tek iş parçacıklı asenkron yaklaşımla tamamen imkansız olan bir şey.
Aslında, tek bir CPU üzerinde yeterli CPU gücüne sahip olmadığınız ve performans için çoklu okuma kullanmak istediğinizde, bunu yapmak genellikle zor olur. Öte yandan, eğer bir CPU yeterli işlem gücü yoksa, genellikle programınızın makul bir zaman diliminde başarmak istediğiniz şeyi yapmasını mümkün kılan tek çözümdür, bu da işi değerli kılar.
Önemsiz Paralellik
Tabii ki, bazen çok iş parçacıklı gerçek hızlanma kolay olabilir .
Çok sayıda bağımsız hesaplama yoğun göreviniz varsa (yani, girdi ve çıktı verileri sonucu belirlemek için yapılması gereken hesaplamalara göre çok küçük olan işler) varsa, o zaman bir iş parçacığı havuzu oluşturmak (uygun CPU sayısına göre uygun şekilde boyutlandırılır) ve bir ana iş parçacığının işi dağıtması ve sonuçları toplaması.
Performans İçin Pratik Çoklu Okuma
Kendimi çok fazla uzman olarak öne sürmek istemem, ama benim izlenimim, genel olarak, bugünlerde gerçekleşen performansa ilişkin en pratik okuyucunun önemsiz paralelliğe sahip bir uygulamadaki yerleri aramak ve çoklu iplikler kullanmak olduğu yönünde. yararları elde etmek için.
Herhangi bir optimizasyonda olduğu gibi, programınızın performansını belirledikten ve etkin noktaları belirledikten sonra optimizasyon yapmak genellikle daha iyi olur: Bir programın bu kısımda bir kısımda ve o kısımda başka bir kısımda çalışması gerektiğine karar vererek keyfi bir şekilde yavaşlatmak kolaydır. Öncelikle her iki parçanın da CPU zamanının önemli bir kısmını alıp almadığını belirlemek.
Ek bir iş parçacığı daha fazla kurulum / ayırma maliyeti ve daha fazla bağlam anahtarı veya daha fazla CPU arası iletişim maliyeti anlamına gelir. Ayrı bir CPU'daysa bu masrafları telafi etmek için yeterli iş yapmıyorsa ve duyarlılık nedenleriyle ayrı bir konu olması gerekmiyorsa, işleri faydasız hale getirecek yavaşlar.
Çok az bağımlılığa sahip olan ve programınızın çalışma zamanının önemli bir bölümünü kaplayan görevleri arayın.
Karşılıklı bağımlılıkları yoksa, o zaman önemsiz bir paralellik durumu söz konusudur, her birini bir iplikle kolayca kurabilir ve avantajlardan yararlanabilirsiniz.
Sınırlı karşılıklı bağımlılıkta görevler bulabilirseniz, bilgi alışverişinde bulunmak için kilitleme ve senkronizasyon onları önemli ölçüde yavaşlatmaz, o zaman çoklu okuma, senkronizasyon sırasında hatalı mantık nedeniyle kilitlenme tehlikelerinden kaçınmak için dikkatli olmanız koşuluyla biraz hız kazanabilir. gerektiğinde senkronize olmama nedeniyle hatalı sonuçlar
Alternatif olarak, çok iş parçacıklı okuma için daha yaygın olan uygulamaların bazıları (bir anlamda) önceden belirlenmiş bir algoritmanın hızlandırılmasını istemiyor, bunun yerine algoritma için daha büyük bir bütçe yazmayı planlıyorlar: bir oyun motoru yazıyorsanız ve AI'niz kare hızınıza göre bir karar vermek zorundadır, eğer kendi CPU'sunu verirseniz AI'nıza genellikle daha büyük bir CPU döngüsü bütçesi verebilirsiniz.
Bununla birlikte, dişlilerin profilini çıkardığınızdan ve bir noktada maliyeti telafi etmek için yeterli işi yaptıklarından emin olun.
Paralel Algoritmalar
Ayrıca birden fazla işlemci kullanarak hızlanabilen birçok sorun var, ancak bunlar CPU'lar arasında kolayca bölünemeyecek kadar monolitik.
Paralel algoritmalar, en iyi paralel olmayan algoritmaya göre büyük O çalışma süreleri için dikkatlice analiz edilmelidir, çünkü CPU-içi iletişim maliyetinin birden fazla CPU kullanmanın yararlarını ortadan kaldırması çok kolaydır. Genel olarak, CPU'lar arası iletişimi (büyük O terimleriyle) her CPU'da hesaplamaları kullandıklarından daha az kullanmaları gerekir.
Şu anda, kısmen, gereken karmaşık analizler nedeniyle, kısmen önemsiz paralellik oldukça yaygın olduğu için, kısmen, bilgisayarlarımızda sorun çıkaran çok fazla CPU çekirdeğine sahip olmadığımız için, kısmen büyük ölçüde akademik araştırmalar için bir alandır. Bir CPU üzerindeki makul bir zaman diliminde çözülemeyen tüm CPU'larımızı kullanarak makul bir zaman diliminde çözülebilir.