Unity coroutine vs konuları


13

Koroutin ve evre arasındaki fark nedir? Birini diğerinin üzerinde kullanmanın herhangi bir avantajı var mı?


3
Ana iş parçacığı üzerinde çalışan cohoutines.
Woltus


2
Bir iş parçacığında herhangi bir Unity işlevi kullanamazsınız. Coroutines yapabilir.
Hellium


1
@Hellium Correction, farklı bir iş parçacığında Unity işlevlerini kullanamazsınız, yani Ana iş parçacığında Unity işlevleri kullanılabilir .
Pharap

Yanıtlar:


24

Coroutines ilk bakışta iş parçacıkları gibi görünse de, aslında herhangi bir çok iş parçacığı kullanmıyorlar. Onlar kadar sırayla yürütülür yield. Motorunun kendi ana döngünün bir parçası olarak (işaret aynen türüne bağlıdır ne tüm vermiştir coroutines kontrol edecek yield, daha fazla bilgi için bu şemasını kontrol ,) onların sonraki dek arka arkaya devam yield, sonra ana döngü devam edin.

Bu teknik, gerçek çoklu kullanım ile ilgili sorunların neden olduğu baş ağrıları olmadan coroutines kullanabilmeniz avantajına sahiptir. Bağlam anahtarlarından kaynaklanan herhangi bir kilitlenme, yarış durumu veya performans sorunu yaşamayacaksınız, düzgün bir şekilde hata ayıklayabileceksiniz ve iş parçacığı için güvenli veri kapları kullanmanıza gerek yok. Bunun nedeni, bir koroutin yürütülürken, Birlik motorunun kontrollü bir durumda olmasıdır. Unity işlevlerinin çoğunu kullanmak güvenlidir.

Diğer taraftan, iş parçacıklarıyla, Unity ana döngüsünün şu anda hangi durumda olduğu hakkında kesinlikle hiçbir bilginiz yoktur (aslında artık hiç çalışmıyor olabilir). Bu nedenle, iş parçanız, o şeyi yapması gerekmeyen bir zamanda bir şey yaparak oldukça fazla tahribat yaratabilir. Bir alt diziden yerel Unity işlevlerine dokunmayın . Bir alt-iş parçacığı ve ana iş parçacığı arasında iletişim kurmanız gerekiyorsa, iş parçacığının iş parçacığı için güvenli (!) Bir kapsayıcı nesnesine yazmasını ve bir MonoBehaviour'un her zamanki Unity olay işlevleri sırasında bu bilgileri okumasını sağlayın.

"Gerçek" çoklu iş parçacığı yapmamanın dezavantajı, CPU yoğun hesaplamaları birden fazla CPU çekirdeği üzerinde paralel hale getirmek için yardımcı programları kullanamamanızdır. Bununla birlikte, bir hesaplamayı birden fazla güncellemeye bölmek için kullanabilirsiniz. Yani oyununuzu bir saniyeliğine dondurmak yerine, birkaç saniye içinde daha düşük bir ortalama kare hızı elde edersiniz. Ancak bu durumda yieldUnity'nin bir güncelleme çalıştırmasına izin vermek istediğinizde ortak programınızdan sorumlusunuz .

Sonuç:

  • Oyun mantığını ifade etmek için eşzamansız yürütme kullanmak istiyorsanız, coroutines kullanın.
  • Birden fazla CPU çekirdeği kullanmak için eşzamansız yürütme kullanmak istiyorsanız, iş parçacıkları kullanın.

Yorumlar uzun tartışmalar için değildir; bu görüşme sohbete taşındı .
MichaelHouse

10

Coroutines, Bilgisayar Biliminde "kooperatif çoklu görev" olarak adlandırdığımız şeydir. Birden fazla farklı yürütme akışının birbirleriyle işbirliği içinde bir araya gelmesinin bir yoludur. İşbirlikli çoklu görevde, bir yürütme akışı CPU'nun a yield. Bu noktada Unity (veya hangi çerçeveyi kullanırsanız kullanın) farklı bir yürütme akışına geçme seçeneğine sahiptir. Daha sonra CPU'ya kadar tamamen tartışmasız sahipliğini alır yield.

Konular "önleyici çoklu görev" olarak adlandırdığımız şeydir. İş parçacıklarını kullanırken, çerçeve her zaman iş parçacığınızı düşünmeyi durdurma ve başka bir iş parçacığına geçme hakkını saklı tutar . Nerede olduğun önemli değil. Hatta bazı durumlarda belleğe bir değişken yazarak kısmen de durdurabilirsiniz!

Her biri için artıları ve eksileri vardır. Koroutinlerin eksileri muhtemelen anlaşılması en kolay olanlardır. İlk önce, eşgüdümlerin hepsi tek bir çekirdek üzerinde yürütülür. Dört çekirdekli bir CPU'nuz varsa, yardımcı programlar dört çekirdekten yalnızca birini kullanır. Bu işleri basitleştirir, ancak bazı durumlarda bir performans sorunu olabilir. İkinci koşul, herhangi bir ortak programın tüm programınızı sadece reddederek durdurabileceğinin farkında olmanızdır yield. Bu, yıllar önce Mac OS9'da bir sorundu. OS9 yalnızca tüm bilgisayarda ortak çoklu görevleri destekledi. Programlarınızdan biri asılı kalırsa, bilgisayarı o kadar şiddetli bir şekilde durdurabilir ki, işletim sistemi ne olduğunu bildirmek için hata mesajı metnini bile oluşturamadı!

Coroutines'in artıları, anlaşılmaları nispeten kolaydır. Sahip olduğunuz hatalar çok daha öngörülebilir. Ayrıca tipik olarak daha az kaynak gerektirirler, bu da binlerce binlerce koroutin veya iş parçacığına tırmanırken yardımcı olabilir. Candid Moon yorumlarda, konuları düzgün çalışmadıysanız, sadece coroutines'e sadık kaldığından ve haklı olduklarından bahsetti. Birlikte çalışan programlarla çalışmak çok daha kolaydır.

İplikler tamamen farklı bir canavardır. Her zaman başka bir iş parçacığının sizi her zaman kesebileceği ihtimaline karşı daima tetikte olmalısınızve verilerinizi karıştırın. İş parçacığı kitaplıkları, işletim sistemine diğer iş parçacıklarınızdan birini çalıştırmanın güvenli olduğu ve güvenli olmadığı zaman bildirmenize yardımcı olan muteksler ve koşul değişkenleri gibi, size yardımcı olacak güçlü araçların tüm paketlerini sağlar. Bu araçların nasıl kullanılacağına dair tüm kurslar var. Ortaya çıkan ünlü konulardan biri, bir "kilitlenme" dir, bu da iki iş parçacığının diğerinin bazı kaynakları serbest bırakmasını bekleyerek "sıkışıp kalması" dır. Unity için çok önemli olan bir başka sorun da, birçok kütüphane (Unity gibi) birden çok evreden gelen çağrıları destekleyecek şekilde tasarlanmamıştır. Hangi çağrılara izin verildiğine ve hangilerinin yasak olduğuna dikkat etmezseniz, çerçevenizi kolayca kırabilirsiniz.

Bu ekstra karmaşıklığın nedeni aslında çok basittir. Önleyici çoklu görev modeli, yalnızca diğer iş parçacıklarını kesmekle kalmayıp aynı zamanda iş parçacıkları farklı çekirdeklerde yan yana çalıştırmanıza izin veren çok iş parçacıklı modele gerçekten benzer . Bu inanılmaz derecede güçlü, çıkan yeni dört çekirdekli ve onaltılı kod CPU'ları gerçekten kullanmanın tek yolu olmakla birlikte, pandoras kutusunu açıyor. Çok iş parçacıklı bir dünyada bu verilerin nasıl yönetileceğine ilişkin senkronizasyon kuralları olumlu bir şekilde acımasızdır. C ++ dünyasında, MEMORY_ORDER_CONSUMEçok iş parçacıklı senkronizasyonun bir itty-bitty-teeny-weenie köşesi olan tüm makaleler var .

Peki diş açmanın eksileri? Basit: Zorlar. Daha önce hiç görmediğiniz tüm böcek sınıflarına rastlayabilirsiniz. Birçoğu bazen ortaya çıkan "heisenbugs" olarak adlandırılır ve hata ayıkladığınız zaman kaybolur. Bunlarla başa çıkmak için size verilen araçlar çok güçlüdür, ancak aynı zamanda çok düşük seviyededir. Kullanımı kolay olacak şekilde tasarlanmaktan ziyade modern yongaların mimarileri üzerinde verimli olacak şekilde tasarlanmıştır.

Ancak, tüm CPU gücünüzü kullanmak istiyorsanız, ihtiyacınız olan araçtır. Ayrıca, orada vardır aslında OS kolu kesintileri gerçekleşebilir nerede tüm sorular izin çünkü onlar değiş tokuş eden kavramlar ile olduğundan daha çoklu kullanım anlamak daha kolaydır algoritmaları.

Candid Moon'un coroutines'e yapışması hakkındaki yorum da benim tavsiyem. İpliklerin gücünü istiyorsanız, o zaman taahhüt edin. Dışarı çıkın ve resmi olarak konuları gerçekten öğrenin. Güvenli ve güvenilir tekrarlanabilir sonuçlar elde edebilmeniz ve performansınızı gittikçe artırabilmeniz için, konuları düşünmenin en iyi yolunu nasıl organize edeceğimizi anlamanız için birkaç on yıl geçirdik. Örneğin, tüm aklı başında dersler koşul değişkenlerini öğretmeden önce muteksleri öğretecektir. Atomikleri kapsayan tüm aklı başında dersler atomların varlığından bahsetmeden önce muteksleri ve koşul değişkenlerini tam olarak öğretecektir. (Not: atomik bir aklı başında öğretici diye bir şey yoktur.) Parçalı ipliği öğrenmeye çalışın ve migren için yalvarıyorsunuz.


İş parçacıkları, esas olarak işlemlerin ve bağımlılıkların araya girdiği durumlarda karmaşıklık katar. Ana oyun döngüsü üç işlev içeriyorsa, x (), y () ve z () ve hiçbiri diğerinin ihtiyaç duyduğu herhangi bir şeyi etkilemez, üçünü de aynı anda başlatır, ancak devam etmeden önce herkesin tamamlanmasını bekleyebilir çok fazla karmaşıklık eklemek zorunda kalmadan çok çekirdekli bir makineden biraz faydalanmasına izin verin. Koşul değişkenleri genellikle mutekslerle birlikte kullanılırken, bağımsız paralel adımlar paradigması gerçekten böyle mutekslere ihtiyaç duymaz ...
Supercat

... ancak sadece y () ve z () işleyen iş parçacıklarının tetikleninceye kadar beklemelerinin bir yolu ve sonra ana iş parçacığının x () çalıştırdıktan sonra y () ve z'ye kadar beklemesinin bir yolu () tamamlandı.
supercat

@supercat Bağımsız paralel fazlar ve sıralı fazlar arasında geçiş yapmak için her zaman bazı senkronizasyonlara sahip olmanız gerekir . Bazen bu a'dan başka bir şey değildir join(), ama bir şeye ihtiyacınız vardır. Senkronizasyonu sizin için yapacak bir sistem tasarlayan bir mimarınız yoksa, bunu kendiniz yazmalısınız. Çok iş parçacıklı şeyler yapan biri olarak, insanların bilgisayarların nasıl çalıştığına dair zihinsel modellerinin, senkronizasyonu güvenli bir şekilde yapmadan önce ayarlanması gerektiğini (iyi derslerin öğreteceği şey) buluyorum
Cort Ammon

Tabii ki bazı senkronizasyonlar olmalı ve en yüksek verimi elde etmek genellikle bundan daha fazlasını gerektirecektir join. Demek istediğim, diş açmanın olası performans faydalarının ılımlı bir fraksiyonunu takip etmenin, bazen daha büyük bir fraksiyonu elde etmek için daha karmaşık bir diş açma yaklaşımı kullanmaktan daha iyi olabileceğiydi.
supercat

Yeni hata türleri hakkında: kodun güvenli olduğunu mantıklı bir şekilde kanıtlayamıyorsanız, kapıdan nasıl buggy olacağını bilmek imkansızdır. Yürütme sırası tanımlanmamış olsa da, 1 makinede her çalıştırdığınızda genellikle benzer yollar kullanır. Sıklıkla makinenin bir kısmında zor ve çoğu zaman başarısız olduğunu göreceksiniz ve muhtemelen tüm olası makineleri test edemezsiniz. İş yerinde, makinelerimizin yalnızca 1 tanesinde tezahür eden bir hata vardı; birden fazla insanın izini sürmesi uzun zaman aldı. Vahşi doğada bunu istemiyorum. Sadece senkronizasyonu test etmeyin, mantıksal olarak kanıtlayın.
Aaron

2

Mümkün olan en basit terimlerle ...


İş Parçacığı

Bir iş parçacığı ne zaman vereceğine karar vermez, işletim sistemi ('OS', örneğin Windows) bir iş parçacığı ne zaman verileceğine karar verir. İşletim sistemi, iş parçacıklarını zamanlamaktan neredeyse tamamen sorumludur, hangi iş parçacıklarının çalıştırılacağına, ne zaman çalıştırılacağına ve ne kadar süreyle verileceğine karar verir.

Ayrıca bir iş parçacığı eşzamanlı olarak (bir iş parçacığı birbiri ardına) veya eşzamansız olarak (farklı CPU çekirdeklerinde çalışan farklı iş parçacıkları) çalıştırılabilir. Zaman uyumsuz olarak çalışabilme özelliği, iş parçacıklarının aynı zamanda daha fazla iş yapabileceği anlamına gelir (çünkü iş parçacıkları tam anlamıyla aynı anda iki şey yapıyor). Senkronize iş parçacıkları bile, işletim sistemi onları programlamakta iyi olursa çok iş yapar.

Bununla birlikte, bu ekstra işlem gücü yan etkilerle birlikte gelir. Örneğin, iki iş parçacığı aynı kaynağa (örneğin bir liste) erişmeye çalışıyorsa ve her iş parçacığı kodun herhangi bir noktasında rasgele durdurulabilirse, ikinci iş parçacığının değişiklikleri ilk iş parçacığının yaptığı değişiklikleri engelleyebilir. (Ayrıca bkz: Yarış Koşulları ve Kilitlenme .)

Dişler de 'ağır' olarak kabul edilir, çünkü çok fazla yükleri vardır, bu da dişleri değiştirirken önemli bir zaman cezası olduğu anlamına gelir.


Eşyordamlar

İş parçacıklarından farklı olarak, eş-programlar tamamen eşzamanlıdır, herhangi bir zamanda yalnızca bir eş-zamanlı çalışma yapılabilir. Ek olarak, eşlenikler, ne zaman verileceğini seçer ve bu nedenle kodda uygun olan bir noktada vermeyi seçebilir (örneğin, bir döngü döngüsünün sonunda). Bu durum, yarış koşulları ve çıkmaz kilitler gibi sorunların önlenmesinin çok daha kolay olmasının yanı sıra, programların birbirleriyle işbirliği yapmasını kolaylaştırıyor.

Bununla birlikte, bu da büyük bir sorumluluktur, eğer bir koroutin düzgün bir şekilde vermezse, çok fazla işlemci süresi tüketebilir ve paylaşılan kaynakları yanlış değiştirirse yine de hatalara neden olabilir.

Koroutinler genellikle bağlam değiştirme gerektirmez ve bu nedenle içeri ve dışarı hızlıca geçiş yapar ve oldukça hafiftir.


Özetle:

Konu:

  • Senkron veya Asenkron
  • OS tarafından sağlandı
  • Rastgele verim
  • Ağır

eşyordam:

  • Senkron
  • Kendini verir
  • Seçime göre verim
  • Hafif

İpliklerin ve koroutinlerin rolleri çok benzer, ancak işi nasıl yaptıkları konusunda farklılık gösterirler, bu da her birinin farklı görevlere daha uygun olduğu anlamına gelir. İş parçacıkları, kesintiye uğramadan kendi başlarına bir şeyler yapmaya odaklanabilecekleri, daha sonra iş bittikten sonra sinyal verebilecekleri görevler için en iyisidir. Eşgüdümler, çok sayıda küçük adımda yapılabilecek görevler ve birlikte veri işlemeyi gerektiren görevler için en iyisidir.

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.