RTOS'taki Kuyrukların Değiştirilmesi


12

Görevler arası iletişim veya RTOS'un iki görevi arasında veri paylaşmak için Kuyrukları kullanırız. Ancak Kuyruklar ile ilgili sorun yavaş olmasıdır .... Onlar Tampon sonra Mutex İşleme ve sonra Veri Aktarımı veri kopyalayın. Büyük veri aktarmanız gerekiyorsa rahatsız edici derecede yavaştır. Başka bir sorun, aynı kuyruğa Birden fazla görev tarafından erişilmesi. Sonra Resim şöyle olur: - Önce Kuyruğa erişmek için bekleyin, sonra Kuyruk dahili Mutex İşleme sonra Veri Aktarımı bekleyin.

Bu sistem üzerindeki ek yükü artırır. Kuyruklar için Verimli Değişim ne olabilir ?

(Sanırım bu soru kullandığımız RTOS'un Bağımsızsı. RTOS'un çoğu Kuyrukları yalnızca bu şekilde ele alıyor)


Birden fazla görevin eriştiği bir kuyruk ile ne demek istiyorsun? Kuyruğa gönderme mi yoksa kuyruktan okuma mı demek istediniz? Birden fazla görev, minimum ek yük ile bir kuyruğa mesaj gönderebilmelidir. RTOS, bir postun atomik bir işlem olması için muteksi yapmalıdır. Görevlerin% 99'u için, kuyruğa bekleyen ve iletiyi işleyen bir döngü olmalıdır. Bir kuyruk (genellikle) yalnızca bir görev tarafından okunmalıdır. Muhtemelen tasarımınıza ve bunları değiştirmek yerine kuyrukları nasıl kullandığınıza bakmanız gerekir.
Erik

@Erik: Üzgünüm! Bahsettiğiniz mekanizmayı kullanıyorum .... Başka bir şey söylemek istedim ve farklı yazdım .... Bunu düzenleyeceğim !! Hatayı işaret ettiğiniz için teşekkürler! Kodumdaki kuyruk erişimini bekliyorum!
Swanand

Yanıtlar:


7

Kuyruklar bu şekilde çalışır, çünkü bu görevler arası iletişim için güvenli bir işlem modelidir. Daha az katı olan herhangi bir şemada veri bozulması ve / veya sahiplik sorunlarını riske atıyorsunuz.

Verileri bellekteki bir arabelleğe kopyalayıp sıra öğelerini içeren bir işaretçi mi aktarıyorsunuz, yoksa sıra öğelerindeki tüm verileri kendileri geçirmeye mi çalışıyorsunuz? İşaretçilerden geçmiyorsanız, kuyruk öğelerinden bir kerede bir bayt geçirmek yerine bunu yaparken performansta bir artış elde edersiniz.


2
Ben de aynı şeyi söyleyecektim. Yalnızca sıradaki verilere işaretçiler iletirseniz, hızı artırabilirsiniz, ancak verileri kullanmaya ve değiştirmeye çalışan iki iş parçacığı olmadığından emin olun.
Kortuk

@Kortuk'un dediği gibi, "Verileri kullanmaya ve değiştirmeye çalışan iki iş parçacığına sahip olmadığınızdan emin olun" ... Bu, ek yükte artış anlamına geliyor ... Fazla işlem istemiyorum! :(
Swanand

Yani Kuyruklar için böyle bir yedek yok ... Veri Kuyruğu yerine, İşaretçi Kuyruğu kullanmam gerekiyor!
Swanand

1
@Swanand uygulamanızı sıralar sadece tek yönlü olacak şekilde planlarsanız (yani, aynı görevi iki görevde asla okumazsınız) ve işaretçide depolanan verileri derhal işledikten sonra ücretsiz olarak veri paylaşımı ile ilgili bir sorun yaşamamalısınız. Verileri ileri geri güvenilir bir şekilde iletmek için birden fazla kuyruk oluşturmanız gerekebileceğinden genel masraflar artacaktır, ancak bu çok görevli bir ortamda iş yapmanın maliyeti.
AngryEE

7

Kolay bir yol, kuyruktaki verilere bir işaretçi koymak ve işaretçiyi kullanarak verileri tüketmektir.

Aşağıdakilerden emin olmak için performans güvenliği için bu şekilde işlem yaptığınızı unutmayın:

  1. arabellek, tüketici verileri tüketene kadar geçerli kalır
  2. birisi arabelleği yeniden konumlandırır

Dinamik olarak ayrılmış bellek kullanmıyorsanız, onu yeniden ayırmanız gerekmez, ancak yine de veri tüketilmeden önce bellek alanının yeniden kullanılmadığından emin olmanız gerekir.


6

Tek üretici / tek tüketici durumu için kilitsiz kuyruklar uygulanabilir ve genellikle yazılımınızı çok üreticili veya çok tüketici kuyruğu sayısını en aza indirecek şekilde tasarlayabilirsiniz.

Kilitsiz bir kuyruk şu şekilde oluşturulabilir: İletilecek öğelerin bir dizisini ve ayrıca iki tamsayı, bunları Head and Tail olarak adlandırın. Head, diziye bir sonraki öğenin ekleneceği bir dizindir. Kuyruk, bir sonraki öğenin kaldırılabileceği dizinin bir dizinidir. Üretici görevi, bir öğe eklemek için yer olup olmadığını belirlemek için H ve T'yi okur; öğeyi H dizinine yazar, ardından H'yi günceller. Tüketici görevleri, kullanılabilir veri olup olmadığını belirlemek için H ve T'yi okur, T dizinindeki verileri okur, ardından T'yi günceller. Temel olarak iki görevle erişilen bir halka arabelleği ve işlem sırası (ekleme, sonra H güncelleme; kaldırma, ardından T güncelleme) veri bozulmalarının olmamasını sağlar.

Birden fazla üretici ve tek bir tüketici veya tek bir üretici ve birden fazla tüketici ile ilgili bir durumunuz varsa, etkili bir şekilde bir tür kaynak sınırlamanız vardır ve bunun için senkronizasyon kullanmaktan başka bir şey yoktur, çünkü performans sınırlayıcı daha olasıdır kilitleme mekanizmasına sahip bir işletim sistemi yükünden ziyade yalnız üretici / tüketici olmak.

Ancak birden fazla üreticiniz VE tüketiciniz varsa, daha koordineli bir iletişim mekanizması elde edemeyeceğinizi görmek için (tasarım alanında) zaman harcamaya değer; böyle bir durumda, her şeyi tek bir kuyrukta serileştirmek, kuyruğun verimliliğini kesinlikle performansın merkezi belirleyicisi yapar.


1
Bunu + 1'leyecektim, ancak yanılıyorsunuz: birden fazla okuyucu ve yazar için kilitsiz kuyruklar uygulamak mümkündür, bunlar daha karmaşıktır. (Michael + Scott'ın Lock-Free Queues google.com/search?q=michael%20scott%20queue ile ilgili makalesine bakın )
Jason S,

1
@ Jason S - Scott gazetesi özellikle kilitsiz takma ve çıkarma işlemleri için yeniden giriş talep ediyor mu? Eğer öyleyse, bunu çıkarabilir ve gönderebilirseniz, lütfen yapın, birçokları için paha biçilmez bir varlık olacaktır. Okuyucu, belirtilen kağıdın özel makine talimatlarını kullandığını, ancak yukarıdaki yazıdaki konumumun böyle bir talimatı kabul etmediğini not etmelidir.
JustJeff

1
Evet, kilitsiz algoritmaların maliyeti genellikle CAS'a veya eşdeğer talimatlara dayanır. Ancak burada yeniden giriş nasıl gerçekleşir? Muteksler + kilitleme yapıları için mantıklıdır, ancak veri yapısı işlemleri için mantıklı değildir.
Jason S

2

Kuyruğun kendisi bir yük deposuna özel, karşılaştırma-değişim veya benzer ilkel ile çalışacak kadar küçük öğeleri barındırıyorsa, kilitsiz çok üreticili tek tüketici kuyruğunda verimli bir işlem elde edilebilir ve bir boş bir kuyruk aralığı için ayrılmış değer veya ayrılmış değerler. Kuyruğa yazarken, yazar verilerini bir sonraki boş yuvaya kaydetmeye çalışmak için bir karşılaştırma değişimi yapar; bu başarısız olursa, yazar aşağıdaki yuvayı dener. Sıra bir sonraki boş yuvaya bir işaretçi bulundursa da, işaretçi değeri "tavsiye" tir. Bir sistem, load-store-exclusive yerine karşılaştırma-değişim kullanıyorsa, farklı 'boş yuva' değerlerinden oluşan bir 'aileye' sahip olmanız gerekebilir. Aksi takdirde, yazar boş bir kuyruk yuvası bulur ve yazmaya yazmaya çalışırsa, başka bir yazar slotu yazar ve okuyucu okur, ilk yazar bilmeden verilerini okuyucunun göremeyeceği bir noktaya yerleştirir. Bu sorun, load-store-exclusive kullanan sistemlerde oluşmaz, çünkü store-exclusive, eski değerine yazılmasına rağmen verilerin yazıldığını algılayacaktır.


1

Sıranın üzerine yazarak sıralara daha verimli bir şekilde erişebilirsiniz. Normalde RTOS'ların çoğu, kuyruğun önüne muteks almayı gerektirmeyen ekleme desteği verir. Ancak, verileri daha hızlı yürütmek istediğinizde mümkün olduğunca minimum kuyruğun önüne eklemeyi kullandığınızdan emin olun. Normalde kuyruk yapıları maksimum boyut sınırına sahiptir, bu nedenle tüm verileri kuyruğa koymayabilirsiniz, bu nedenle işaretçiyi geçmek her zaman kolaydır.

şerefe !!


1

Kuyruklar doğal olarak yavaş değildir. Bunların uygulanması olabilir.

Verileri körü körüne kopyalayıp senkronize bir kuyruk kullanıyorsanız, bir performans isabeti görürsünüz.

Diğer posterlerin de belirttiği gibi, kilitsiz alternatifler var. Tek-üretici / tek-tüketici durumu basittir; birden fazla üretici ve tüketici için, Michael ve Scott'ın (bunlar soyadı) kilidi olmayan kuyruk algoritması standarttır ve Java'nın ConcurrentLinkedQueue için temel olarak kullanılır .

Belirli durumlarda kuyruk ihtiyacını optimize etmek mümkündür, ancak görevleri ayrıştırmanıza izin vererek sistemlere genellikle büyük basitleştirme avantajları sağlayan eşzamanlılık garantileri sağlarlar.


Michael & Scott gazetesinden: "evrensel bir atomik ilkel sağlayan makineler için açık bir seçim algoritmasıdır (örn. Karşılaştırmalı ve takas veya yük bağlı / mağaza şartlı)". Bu aslında bir iş parçacığını tam olarak kilitlemese de , burada devam eden bir senkronizasyon biçimi vardır.
JustJeff

haklısın; bir bellek engeline özel erişimden dolayı eşzamanlılık gereksinimini azaltabilir.
Jason S
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.