Modern CPU'larda tek atama ADT yönelimli kodun performansı


32

Tek bir atama sahip değişmez verilerde çalışmak, daha fazla bellek gerektirmenin açık bir etkisine sahiptir, biri varsayılır, çünkü sürekli yeni değerler yaratıyorsunuzdur (kapakların altındaki derleyiciler bu sorunu daha az yapmak için işaretçi püf noktaları yaparlar).

Ancak birkaç kez duydum ki, performanstaki kayıpların CPU'nun (özellikle bellek denetleyicisinin) belleğin mutasyona uğramamış olmasından (çok fazla) faydalanabileceği kazanımlar karşısında ağır basmış olduğunu duydum.

Birinin bunun nasıl doğru olduğuna (ya da değilse?) Işık tutabileceğini umuyordum .

Başka bir yazıya yapılan yorumda, Soyut Veri Türlerinin (ADT) beni daha fazla meraklandırmak zorunda kalmasıyla ilgisi olduğu belirtildi, ADT'ler özellikle CPU'nun bellekle uğraşma şeklini nasıl etkiler? Ancak bu bir yana, çoğunlukla sadece dilin saflığının CPU'nun ve önbelleklerinin performansını nasıl etkilediğini merak ediyorum.


2
Bu o okuyor ederken okuyucu atomik bir anlık kapmak ve onu mutasyona etmeyeceğini bilerek güvenli olabilir nerede, çoklu kullanım için oldukça yararlıdır
mandal ucube

@ ratchetfreak Programlama açısından kodunuzun daha fazla güvenlik garantisi sağladığını anlıyorum; bellek denetleyicisi için daha verimli olduğunu söyleyen zamanlarla dolu bir el hakkında ve düşük seviye ayrıntılarını bunun doğru veya doğru olup olmadığını söyleyecek kadar iyi bilmiyorum.
Jimmy Hoffa

Doğru olsa bile, hafızada daha az değişiklik yapılmasının değişmezlik için en iyi satış noktası olduğunu düşünmüyorum. Sonuçta, bellek değiştirilmek üzere orada ve CPU'lar ve bellek yöneticileri yıllar içinde bu konuda oldukça başarılı oldu.
Rein Henrich,

1
Değişmez yapıları kullanırken bellek verimliliğinin mutlaka derleyici optimizasyonlarına bağlı olması gerekmediğini de belirtmek isterim. Bu örnekte let a = [1,2,3] in let b = 0:a in (a, b, (-1):c)paylaşım hafıza gereksinimlerini azaltır, fakat derleyicinin tanımına (:)ve tanımına bağlıdır []. Bence? Bunun hakkında emin değilim.

Yanıtlar:


28

CPU (özel olarak bellek denetleyicisi), belleğin mutasyona uğramamış olmasından faydalanabilir

Avantajı bu gerçeği kullanarak derleyici kazanç sağlamışlardır membar veri erişildiğinde talimatları.

Ayrıca bir bellek, bellek çiti veya çit talimatı olarak da bilinen bir bellek bariyeri, merkezi bir işlem biriminin (CPU) veya derleyicinin, bariyer talimatından önce ve sonra verilen bellek işlemlerinde bir sipariş kısıtlaması uygulamasına neden olan bir bariyer talimatı türüdür. Bu, tipik olarak, belirli işlemlerin bariyerden önce ve sonra başkalarının gerçekleştirilmesinin garanti edildiği anlamına gelir.

Bellek engelleri gereklidir, çünkü çoğu modern CPU, sıra dışı çalıştırma ile sonuçlanabilecek performans optimizasyonları kullanır. Bellek işlemlerinin bu yeniden sıralanması (yükler ve depolar) normal olarak tek bir yürütme iş parçacığında fark edilmez, ancak eşzamanlı programlarda ve aygıt sürücülerinde dikkatlice kontrol edilmedikçe öngörülemeyen davranışlara neden olabilir ...


Verilere farklı iş parçacıklarından erişildiğinde, çok çekirdekli işlemcide şu şekilde devam eder: farklı iş parçacıkları her biri kendi (çekirdeğinde yerel) önbellek - farklı bir genel önbellek kopyası kullanarak çalıştırır.

Verilerin değişebilir olması ve programcının farklı dişler arasında tutarlı olması gerekiyorsa, tutarlılığı garanti altına almak için önlemler alınması gerekir. Programcı için bu , belirli bir iş parçacığı içindeki verilere eriştikleri (örn. Okunan) olduğunda senkronizasyon yapılarının kullanılması anlamına gelir .

Derleyici için, koddaki senkronizasyon yapısı , çekirdeklerden birindeki veri kopyasında yapılan değişikliklerin, diğer çekirdeklerdeki önbelleklerin güvenliğini sağlamak için uygun şekilde yayıldığından ("yayınlandı") emin olmak için bir membar komutunun eklenmesi gerektiği anlamına gelir. Aynı (güncel) kopyaya sahip olmak.

Biraz sadeleştirici, aşağıdaki notu görün , işte membar için çok çekirdekli işlemci:

  1. Tüm çekirdekler işlemeyi durdurur - yanlışlıkla önbelleğe yazmaktan kaçınmak için.
  2. Yerel önbelleklerde yapılan tüm güncellemeler, genel önbelleğe geri yazılır - genel önbelleğin en yeni verileri içerdiğinden emin olmak için. Bu biraz zaman alıyor.
  3. Güncellenen veriler genel önbellekten yerel olanlara geri yazılır - yerel önbelleklerin en yeni verileri içerdiğinden emin olmak için. Bu biraz zaman alıyor.
  4. Tüm çekirdekler yürütmeye devam eder.

Görüyorsunuz, küresel ve yerel önbelleklerin arasında veri ileri geri kopyalanırken tüm çekirdekler hiçbir şey yapmıyor . Değişebilir verilerin uygun şekilde senkronize edildiğinden emin olmak için bu gereklidir (iş parçacığı güvenli). 4 çekirdek varsa, 4'ü durdurun ve önbellekler eşitlenirken bekleyin. 8 varsa, tüm 8 durur. Eğer 16 varsa ... bunlardan birinde yapılması gerekenleri beklerken tam olarak hiçbir şey yapmadan 15 çekirdeğiniz var.

Şimdi, veriler değişken olduğunda ne olacağını görelim? Hangi dişe erişirse baksın, aynı olması garanti edilir. Programcı için bu , belirli bir konudaki verilere eriştiğinde (okuduğunda) senkronizasyon yapıları eklemenin gerekmediği anlamına gelir .

Derleyici için bu, sırayla bir talimat talimatı eklemenize gerek olmadığı anlamına gelir .

Sonuç olarak, verilere erişimin, çekirdeklerin durması ve verilerin küresel ve yerel önbelleklerin arasında ileri geri yazılması sırasında beklemesi gerekmez. Bu , hafızanın değişmemesinin bir avantajı .


Not biraz basitleştirilmesi yukarıdaki açıklama verileri biraz daha karmaşık olumsuz etkiler, örneğin, değişken olmak damla ardışık . İstenilen siparişi garanti etmek için, CPU'nun veri değişikliklerinden etkilenen hatları geçersiz hale getirmesi gerekiyor - bu da bir başka performans cezası. Bu, basit (ve dolayısıyla güvenilir :) tüm boru hatlarının geçersiz kılınması ile gerçekleştirilirse, negatif etki daha da güçlendirilir.



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.