1 puan yazan GN⁺ 2024-07-28 | 1 yorum | WhatsApp'ta paylaş
  • AMD Zen 5, Zen mimarisinin baştan aşağı yeniden tasarımı içinde 2-Ahead Branch Predictor'ı tanıttı ve 1990'lardaki çoklu blok ileri branch prediction araştırmalarını modern x86 ön uç genişlemesine yeniden taşıdı
  • Branch prediction, CPU ön ucunun koşullu branch sonucu çıkmadan da komut getirmeyi sürdürmesini sağlayan mekanizmadır; yanlış tahmin ise pipeline flush ve yeniden başlatma maliyetine yol açar
  • Zen 5, 32KB L1 komut önbelleğinde 32 bayt/döngü fetch pipe 2 adet kullanıyor ve bunların her birini 4-wide decode cluster'a bağlıyor; Op Cache de dual-ported 6-wide yapıyla Op Queue'ya en fazla 12 operand sağlıyor
  • Yeni yapı, tek döngüde 2 taken branch'i birbirini izlemeyen komut blokları boyunca işliyor ve 5 bitlik length field ile üçüncü tahmin penceresinin başlangıç noktasını bulup decode ve Op Cache kaynaklarının aşırı kullanımını azaltıyor
  • x86'da değişken uzunluklu komutlar nedeniyle komut sınırı belirlemeyi paralelleştirmek zor olduğundan, 2-Ahead Branch Predictor ve çift fetch·decode yapısı Zen ailesi ön ucunun genişlemesindeki temel değişiklik haline geliyor

Zen 5 ön ucunda değişen noktalar

  • AMD, Zen 5'i Zen mimarisinin baştan aşağı yeniden tasarımı olarak tanıttı ve 2-Ahead Branch Predictor da bu değişimin öne çıkan parçalarından biri
  • Bu yapı, 30 yıl önceki makalelerde ele alınan fikirlere dayanıyor ve tek çekirdek performansını daha da yükseltme eğilimi içinde yeniden ortaya çıkıyor
  • Birden fazla taken branch'i aynı anda tahmin etmek, ön ucun daha uzaktaki komut akışını da önceden görebilmesini sağlıyor

Branch prediction CPU pipeline'ı için neden gerekli?

  • Modern CPU'lar, komut getirme (fetch), decode ve yürütmeyi birden fazla aşamaya bölen pipeline yapısını kullanır
  • Koşullu bir branch olduğunda ön uç, koşul değerlendirmesi bitmeden önce sıradaki getirilecek komutun konumunu belirlemek zorundadır
  • Olası seçenekler temelde iki tanedir
    • Branch sonucu çıkana kadar durmak
    • Sonraki yolu tahmin etmek; yanlışsa hatalı işi atıp kesin noktadan yeniden başlamak
  • Tahmin yanlışsa, bu tahmine dayanan işlerin pipeline'dan çıkarılması için flush gerekir
  • Branch koşulunda durmanın maliyeti, instruction fetch ile branch condition değerlendirmesinin tamamlanması arasındaki pipeline aşaması sayısıyla orantılıdır
  • Sonuç olarak CPU, programın komut akışını olabildiğince doğru tahmin etmek zorundadır

2-Ahead fikrinin ortaya çıktığı bağlam

  • Basit bir tahmin yöntemi olarak kısa backward jump'ları her zaman taken sayan strateji vardı ve bu, her zaman bir sonraki adresi getirme yaklaşımına kıyasla tarihsel olarak büyük avantaj sağladı
  • Son branch geçmişi ya da adres kayıtları gibi küçük bir durum bilgisini tutmak, gerçek programlarda daha iyi sonuçlar verebiliyordu
  • Yalnızca onlarca KB boyutundaki yapılarla bile yüzde 90'ların sonlarında branch prediction doğruluğu elde edilebiliyordu
  • 2-Ahead Branch Predictor, 1990'ların başından beri tartışılan bir öneri ve o dönemde 8-wide ve üstüne mimari genişliğin çıkarılması sorunu da birlikte ele alınıyordu
  • Sonrasında ticari CPU'lar çok çekirdeğe yönelince, tek tek çekirdeklerin alanı daha önemli hale geldi ve akademi daha alan verimli TAGE predictor iyileştirmelerine odaklandı
  • Üretim süreçlerinin küçülmesiyle benzer alana daha fazla transistör sığdırılabildi; yüzlerce out-of-order CPU'ya kadar ölçeklenen eğilimle birlikte tek çekirdek performansına ilgi de yeniden arttı

x86 ön ucu neden daha zor?

  • 64-bit Arm gibi sabit uzunluklu komut kullanan ISA'larda instruction cache line'ın rastgele bir bölümünü paralel decode etmek kolaydır
    • Girdi verisini garantili komut bayt sınırlarına bölmek ve decoder logic'i kopyalamak yeterlidir
  • x86'da komut uzunluğu değişken olduğu için, her komutun sonraki sınırını bulmak adına instruction byte'larını doğrusal biçimde ayrıştırmak gerekir
  • Prefix'leri önce kısmi decode eden türde bir pipeline ile belli ölçüde paralelleştirme yapılabilir, ancak x86'da bunun maliyeti düşük değildir
  • Performans odaklı x86 çekirdeklerinde 4-wide decode'un uzun süre yaygın olmasının nedeni de budur
  • Intel Golden Cove'un 6-wide decode gibi tasarımları, modern süreçlerde artan mantık yoğunluğu sayesinde ticarileşebildi; ancak monolithic parallel x86 decoding'in alan ve güç maliyeti, genişlik arttıkça super-linear biçimde yükselir
  • Tipik uygulama tamsayı kodlarında branch density kabaca her 5-6 komutta 1 branch düzeyindedir; bu da decoder genişliğini çok daha fazla artırma motivasyonunu azaltır
  • x86 ön ucunun, paralelleştirilmesi zor olan komut sınırı belirleme aşamasını aşacak ve güvenli biçimde bir sonraki komut sınırına ulaşacak bir yönteme ihtiyacı vardır

Zen 5'in çift fetch·decode uygulaması

  • “Multiple-block ahead branch predictors” by Seznec et al., 2-Ahead Branch Predictor'ın gerekçesini ve uygulanışını ele alan temel makaledir
  • Birden fazla taken branch işleyebilen predictor tek başına yeterli değildir; Seznec ve arkadaşları, bunun alan gereksinimini patlatmadan kullanılabilmesi için instruction fetch dual-porting gerektiğini savunur
  • Zen 5, instruction fetch ve Op Cache'i dual-port yapıya çevirdi
    • 32KB L1 instruction cache'ten 32 bayt/döngü fetch pipe 2 adet kullanılıyor
    • Her fetch pipe kendi 4-wide decode cluster'ına bağlı
    • Op Cache, dual-ported 6-wide tasarıma sahip ve Op Queue'ya en fazla 12 operand sağlayabiliyor
  • Branch Target Buffer da dual-porting kapsamına giriyor
    • Zen 5'in erişilebilen 16K entry büyüklüğündeki L1 BTB'si, dual-ported L1 BTB olasılığını açıklayabilir
    • L2 BTB, 8K entry ile L1 BTB'den daha küçük
    • AMD, L2 BTB'yi victim cache'e benzer şekilde kullanıyor; L1 BTB'den çıkarılan entry'ler L2 BTB'ye taşınıyor

Tek döngüde 2 taken branch işleme biçimi

  • Zen 5, tek döngüde birbirini izlemeyen komut blokları boyunca 2 taken branch işleyebiliyor
  • Bu değişiklik, taken branch ile karşılaşıldığında fetch bandwidth kaybını azaltıyor ve iki taken branch'in ötesine kadar tahmin yapabilmeyi sağlıyor
  • İkinci taken branch'ten sonraki instruction stream daha uzağa kadar görülebildiği için üç adet prediction window oluşabiliyor
  • Bu üç prediction window'un tamamı decode için komut üretiminde kullanılabiliyor
  • İkinci prediction window'a 5 bitlik length field ekleniyor
    • Decode veya Op Cache kaynaklarının aşırı rezerve edilmesini önlüyor
    • Pointer'dan daha küçük ama üçüncü prediction window'un başlangıç noktasını veriyor
    • Üçüncü prediction window cache line boundary'yi aştığında, sonraki döngü için prediction lookup index'ine ek durum saklama gereğini ortadan kaldırıyor
    • Üçüncü prediction window, birinci veya ikinci prediction window ile aynı cache line içindeyse, bu kısmi üçüncü pencere tam bir üçüncü prediction window kadar etkili olmuyor

SMT'de kalan kısıtlar

  • Zen 5'te iki thread etkin olduğunda, decode cluster ile eşlenmiş fetch pipe'lar statik olarak bölümleniyor
  • Bu durumda çift fetch çekirdeği gibi davranabilmek için hem L1 instruction cache'ten hem de Op Cache'ten fetch yapılması gerekiyor
  • AMD'nin Op Cache'i dual-port yapmasının nedeni, çift fetch pipeline'ı daha iyi korumak olabilir

Birlikte anılan ilgili makaleler

1 yorum

 
GN⁺ 2024-07-28
Hacker News yorumları
  • Dallanma tahminini ilk uygulamalardan itibaren iyi açıklayan bir yazı olarak https://danluu.com/branch-prediction/ iyi

  • SMT performansının nasıl olacağını merak ediyorum; bu yaklaşımın fayda sağlayıp bir sonraki nesilde daha da inceltileceğini umuyorum
    Zen5c 192 çekirdeğe veya 384 vCPU’ya kadar çıkıyor; gelecek yılki Zen 6c’de 256 çekirdeğin mümkün olacağı düşünülebilir. Çift soketli bir 1U sunucuda bu potansiyel olarak 512 çekirdek, 1024 vCPU demek
    2014’te yaşadığımız web uygulaması ölçekleme sorunları, artık soğutulabildiği sürece tek bir sunucuya sığabilir. vCPU başına yalnızca 1 RPS varsaysak bile, önbellek isabetlerini hariç tutarak 1000 RPS eder; HN ana sayfası bile sunucuya saniyede 1000 sayfa görüntüleme bindirmiyor

    • Web sayfası sunmak ucuz bir iş olduğundan, çekirdekleri doyurmadan önce ağ I/O sınırına ulaşma olasılığı yüksek
      HPC performansının nasıl olacağını merak ediyorum. Soğutmanın kendisi büyük sorun olmayabilir ama bir noktadan sonra doğrudan sıvı soğutma (DLC) gerektiren “ıslak” bir meseleye dönüşebilir
    • Bilişimin 1940’larda kilobayt çağına girmesi gibi, şimdi kilo-çekirdek çağına giriyoruz
      GPU takılı yoğun sunucu raflarını tek bir makine olarak görürsek, zaten yüzlerce kilo-çekirdeğe ulaşmış durumdayız
      Wikipedia ölçeğinde bir hizmetin tek bir sunucudan verilebileceği fikrini kavrayamayan biriyle tartışmıştım; oldukça eğlenceliydi. Bu bir süredir zaten kolay bir şeydi; sadece erişilebilirlik ya da maliyet verimliliği gibi pratik nedenlerle böyle yapılmıyor
    • Tersi de olabilir. CPU pipeline’ı ne kadar iyi kullanılırsa, ikinci bir thread’i araya sıkıştıracak alan o kadar azalır ve SMT avantajı küçülebilir
    • SMT için çok daha fazla benchmark doğrulaması gerekiyor
      Sezgisel olarak, aynı problemi yarı hızda işleyen işler arttıkça bunun bir bellek kullanım maliyeti olması gerekiyormuş gibi geliyor; SMT açıldığında hız kazancı olmadan yalnızca daha fazla bellek kullanan uygulamaların yaygın olup olmadığını merak ediyorum
      Yayımlanmış benchmark’ların önemli bir kısmında, çoğu uygulama çalışma hızında belirgin bir fayda elde etmiyor gibi görünüyor
    • Web uygulaması ölçekleme sorunları genellikle veritabanı gecikmesi etrafında ortaya çıkar
  • Onlarca yıllık bir makalenin o dönemde fazla dikkat çekmeden yayımlanıp, donanım yeterince güçlenince birden en ileri seviye haline gelmesini görmek her zaman ilginç
    Örneğin Z-buffer var. 3D video oyunlarında kullanılır; ilk makalede ortaya çıktığında, konu dışı olduğu için değil, çok fazla bellek gerektirdiği için yan bir ayrıntı gibi ele alınmıştı
    Birkaç on yıl sonra megabaytlar epey ucuzladı ve sonunda tüm gerçek zamanlı 3D renderer’lar bunu kullanmaya başladı

    • Bir başka örnek düşük yoğunluklu eşlik denetimi kodları. Robert Gallager 1962’de keşfetti, ancak hesaplama açısından pratik olmadığı için onlarca yıl terk edildi ve unutuldu
      David MacKay yeniden keşfedene kadar literatürde yaklaşık 38 yıllık bir boşluk varmış gibi görünüyor
      İlk ana akım kullanımı 2003’teydi; bugün WiFi, Ethernet ve 5G’de kullanılıyor
      [1] https://en.wikipedia.org/wiki/Low-density_parity-check_code
      [2] https://scholar.google.com/scholar?q=%22low+density+parity+c...
    • Mühendisler için böyle gizli kalmış bir akademik kariyer olup olmadığını bazen düşünüyorum
      Kütüphaneye gidip bilgisayar bilimi araştırmacılarının kâğıt makaleler olarak yayımladığı şeyleri okursanız, o dönemde pratik olmayan ama bugün uygulanabilir fikirler bulunabilir
    • Bunun donanım güçlendiği için mümkün hale gelmesinden ziyade, bu tür tasarımların onlarca yıldır mümkün olduğu ama ancak bugünkü trade-off bileşiminde cazip hale geldiği görüşündeyim
      Son 20 yılda tek çekirdek performansı, yatay ölçekleme — yani daha fazla çekirdeğe öncelik verilmesi — nedeniyle baskılandı; bu yüzden tekil çekirdek karmaşıklığı ve kalıp alanı sorun haline geldi. Bu eğilim olmasaydı ve CPU tasarımcıları esas olarak tek çekirdek performansının peşinden gitseydi, çok daha erken bir uygulama görürdük diye düşünüyorum
      Z-buffer basit bir kavram olduğundan makalede yan bir ayrıntı gibi görünmüş olabilir. Daha iyi bir örnek ray tracing olabilir. 3D grafik geçmişiniz olmasa bile kavramın kendisi oldukça nettir, ancak yakın zamana kadar gerçek zamanlı rendering için performans açısından pratik değildi
      İlginç olan, gerçeğe benzer rendering’i yaklaşık olarak sağlayan daha basit bir yaklaşım bulamayıp, eski, biraz saf ve pahalı çözüme geri dönmek zorunda kalmamız
    • Bir başka örnek Rust’ın borrow checker’ı; kökleri onlarca yıl önceki alt-yapısal tip sistemi makalelerine dayanıyor
      Birçok akademisyen alt-yapısal tip sistemlerinin esasen garbage collection karşısında öldüğünü düşünüyordu, ancak Rust bunu o dönemde C++’ın yeni fikirleriyle birleştirerek yeniden canlandırdı
    • Z-buffer yalnızca bir frame buffer kadar ek bellek gerektirmez; piksel başına çok fazla okuma-yazma bant genişliği de gerektirir
      Bu ek bellek bant genişliği gereksinimi, doğru uygulamayı zor ve pahalı hale getirdi. Üst düzey uygulamalar ayrılmış RAM kanalları kullandı, ancak düşük maliyetli donanımlarda paylaşımlı bellek arayüzünün bant genişliğinin önemli bir kısmını tüketti
      Örneğin bazı N64 oyunları, derinlik bilgisini okuma ve güncelleme maliyetinden kaçınmak için Z-buffer’ı kapatıp arka plan/ön plan çizimini yazılımda yöneterek optimize etti
  • Spekülatif tahminciler, özel verileri sızdırmaya yönelik çeşitli saldırıların hedefi olageldi
    Yaygın ISA’ların önemli bir kısmı savunmasızsa, bu tür saldırıların etkisini azaltmak için önlemler alınıp alınmadığını merak ediyorum

    • Zafiyet dal tahmini değil, spekülatif yürütme. Dal tahmincisi yalnızca, işlemcinin kurban programda kodu spekülatif olarak yürütmesi için kandırılması gereken hedef. Üstelik spekülatif yürütmenin sonucunu okuyabilmek için geçerli bir zamanlama kaynağı da gerekir
      Bunu engellemenin, okyanusu kaynatmak düzeyinde bir yaklaşım[0] dışında bir yolu yok. Spekülatif yürütme performans için o kadar değerli ki, onsuz bilgisayarlar neredeyse tamamen kullanılamaz hale gelir. Gerçekten spekülatif yürütmesi olmayan bir işlemci istiyorsanız eski bir birinci nesil Pentium alın
      Pratik azaltımlar çeşitlidir, ancak en azından gizli bilgilere sahip kurban süreç ile kurbanın yürütmesini etkileyebilecek potansiyel saldırgan arasında süreç ayrımı sağlanmalıdır
      Intel, ring’ler arasında spekülatif yürütme yaparken yakalandı; bu yüzden kullanıcı alanından çekirdek ya da hipervizör belleği okunabiliyordu. Tasarımı kötü olmayan bir CPU’da asıl endişelenilmesi gereken şey çoğunlukla HTML iframe’lerdir
      Farklı origin’ler HTTP isteklerini keyfî olarak gönderemez[1], ancak izin almadan birbirlerini içerebilirler[2]. Geleneksel olarak bu bilgi saldırgan sürecine yüklenirdi ve zamanlama saldırısıyla sızdırılabilirdi
      Web’in ilk çözümü iframe’leri süreç olarak ayırmak değil, paylaşımlı bellekli çok iş parçacıklılığın kendisini kaldırmaktı. Saldırgandan zamanlama referansını alırsanız, kurbanın neyi spekülatif yürüttüğünün önemi azalır. Ama bunun için çok iş parçacıklılığı kaldırmak gerekir. Aksi halde bir iş parçacığı, bilinen veriyi döngü içinde tekrar tekrar yazarak bir saat oluşturabilir
      [0] https://hackaday.com/2013/08/02/the-mill-cpu-architecture/
      [1] En azından hedef origin CORS ile izin vermediği sürece mümkün değildir
      [2] Örn. görsel hotlink’i veya iframe gömme
    • Spekülatif yürütmenin sanal bellek çevirisi ve önbellekle etkileştiği nokta istismar edilebilir
      Tahminin kendisinde doğası gereği var olan bir zafiyet değil
  • Bu alanda acemi biri olarak, yazıyı okuduktan sonra da 2-ahead dal tahmincisinin tam olarak ne olduğu net değil

    • Yaklaşık 30 yıl önceki bir kavram olduğu için, 1996 tarihli şu makaleyi[0] işaret ediyor gibi. Benim seviyemi aşan bir konu ama birden çok komut birimi ve yüksek saat hızlarında ortaya çıkan dal tahmini sorunlarına yardımcı oluyor gibi görünüyor
      90’larda bunlardan birine daha yakındı, ancak modern işlemcilerin çoğunda ikisi de var gibi
      “Multiple-block ahead branch predictors” özetinde, mevcut komut bloğundaki bilgiyi bir sonraki komut bloğunun adresini tahmin etmek için kullanmadan, ondan sonraki bloğu tahmin eden bir yöntem olarak açıklanıyor. Bu, geniş dispatch’e sahip “brainiac” işlemcilerde komut getirme darboğazını azaltır ve tek çevrimde iki komut bloğu adresini verimli biçimde tahmin etmeyi sağlar
      Ayrıca “speed demon” işlemcilerde dal tahmini sürecinin pipeline’a alınarak daha yüksek saat hızları veya daha büyük tahmin yapıları üzerinden doğruluk artışı elde edilebileceği söyleniyor. Geleneksel çoklu tahminci yönteminden farklı olarak, birden çok blok ilerisine bakan dal tahmincileri herhangi bir dal tahmini yöntemini kullanabilir
      [0] https://dl.acm.org/doi/10.1145/237090.237169
      Ek olarak, eyegor zaten bağlantıyı paylaşmış gibi ama en azından özete bakın demek istiyorum
    • Anladığım kadarıyla bir sonraki dalın hedefini değil, ondan sonraki dalın hedefini tahmin ediyor
      Bir sonraki dalı tahmin etmekten çok daha zor olur, ama daha derin pipeline’ı besleyecek kodun çok daha erken getirilmesini sağlar
    • Acemi olmasanız da aynı derecede kafa karıştırıcı. Yazı, dal tahmininin en temel yanlarını açıklamaya çok zaman harcıyor; ama iş 2-ahead kısmına gelince açıklamayı atlıyor
    • Tek çevrimde 1 dal değil, 2 dal tahmin ediyor gibi
      Bu yüzden genel dal tahmini gibi yalnızca n+1’i önceden değerlendirmekle kalmayıp n+2 sonucunu da önceden değerlendirebiliyor. Bunun L1 önbelleği bozmadan nasıl çalıştığını pek bilmiyorum
      n+1’in ötesine bakma yöntemi önbellekten atmayı çok daha artıracak gibi geldiğinden, bir şeyi kaçırıyor olmalıyım
      Zen 5’in ikinci taken branch’in ötesindeki komut akışına kadar daha ileri bakabildiği ve bunun sonucunda decode edilecek komutları üretmek için yararlı 3 tahmin penceresine sahip olabildiği söyleniyor
      Özgün makaleye açık erişimle ulaşılabiliyor, ama henüz fazla okuyamadım: https://dl.acm.org/doi/10.1145/237090.237169
    • Genel bir dal tahmincisi, örneğin if-else çalıştırılmadan önce dalın hangi tarafa gideceğini tahmin eder. Böylece CPU komutları önceden getirebilir ve decode edebilir
      Dalın her yönü yeni bir komut bloğunun başlangıcına çıkar ve bu tür blokların son komutu genellikle yine başka bir daldır
      Yani dal tahmincisi, bir sonraki bloğun adresini doğru tahmin eden aygıttır. 2-ahead dal tahmincisi de aynı işi yapar, ama bunu takip eden iki blok için yapar
      Makaledeki ifadeyle, “mevcut komut bloğundaki bilgi, bir sonraki komut bloğundan sonra gelen bloğun adresini tahmin etmek için kullanılır”
      Genel bir dal tahmincisinden farklı olarak, bunun için bir sonraki bloğun komutlarının decode edilmesini beklemek gerekmez. Bu yüzden aynı anda birden çok komut decoder’ını besleyebilir
      Bu, komut decoder’larının darboğaz haline geldiği modern CPU’larda özellikle yararlıdır. Çünkü çevrim başına yalnızca 1 komut decode eden tek bir decoder, çevrim başına 4–6 gibi çok sayıda komut yürütebilen geniş bir front-end’e yetişmekte zorlanır
  • Daha fazla dal ipucu gerekebilir: https://github.com/ziglang/zig/issues/5177
    cold, warm, warmer kullanıp hot’ı varsayılan olduğu için atlamak mümkün olabilir mi diye düşünüyorum. Bazen biri hariç tüm dalları cold olarak işaretlemek de mümkün olabilir

  • Muhtemelen kötü bir fikir ama nedenini bilmek istiyorum
    Koşullu bir dallanma olduğunda olası iki dalın komutlarını da getirip hazırladıktan sonra yanlış tarafı atmak neden olmaz, merak ediyorum
    Bunun çok daha zor bir iş mi olduğunu, yoksa değersiz kılan başka bir neden mi bulunduğunu bilmek istiyorum

    • Bu ikinci en iyi strateji
      Modern TAGE dal tahmincileri %99’un epey üzerinde isabet sağlar. Bu yüzden karşı dalın ek komutları neredeyse her zaman atılır
      Daha kötüsü, ön uç arka ucun gerçek yönü doğrulayabildiği noktadan onlarca dal ileride getirme yapar. Bir sonraki dalda ne yapacaksın? Olası 4 dalı, sonra 8’i, 16’yı, 32’yi mi decode edeceksin? Çoğu atılacak
      Birden fazla komut akışını paralel getirecek donanımın varsa, Intel Gracemont/Goldmont/Skymont ve AMD Zen 5’te olduğu gibi, daha iyi strateji dal tahmincisinin %100 doğru olduğunu varsaymaktır. Bir dalı takip edersin, sonra da bir sonrakini takip edersin
      Intel Skymont’ta 3 decoder var ve her biri 3-wide; bu yüzden sonraki 3 dal hedefini paralel decode ediyor. Intel, büyük kod bloklarını parçalamak için sahte dallar bile ekleyerek üç decoder’ın gelecek komut akışının farklı bölümlerini her zaman decode etmesini sağlıyor. Ardından 3 mikro-işlem akışını birleştirerek Skymont’un çevrim başına 9 komutluk etkin decode bant genişliğini korumasını sağlıyor
      İki dalı da çalıştırmak, dal tahmininin yanlış olduğu nadir durumlarda gecikmeyi yalnızca biraz azaltır. Buna karşılık, bir yönde sonraki iki üç tahmini takip etmeye devam etmek Intel ve AMD’nin birden fazla decoder’ı paralel çalıştırmasını sağlar. Intel daha basit üç adet 3-wide decoder ile 9-wide elde edebilir, AMD ise daha basit iki adet 4-wide decoder ile 8-wide elde edebilir
    • Dal sonucunun rastgele olduğu durumlar nadirdir
      Derleyici, runtime, CPU vb. hangi sonucun daha olası olduğunu çoğu zaman doğru tahmin edebilir ve baştan ek iş yapmamak genellikle daha iyi stratejidir. Yanlış çıkma ihtimaline karşı silisyumu ve ısı bütçesini yanlış cevaba harcamaktan iyidir
      Birçok kişinin dal tahmininin ne kadar doğru olabileceğine dair sezgisi yok gibi. Kendi koduna baksa bile “kontrol akışının çoğu bu tarafa gidiyor, bu dal da istisnai durumu ele almak için var” diye hemen fark eder
      Günümüz derleyicileri de bunu oldukça iyi çıkarıyor; CPU/JIT/runtime da etkileyici sezgisel yöntemler oluşturabiliyor. Yine de başarısız olduğunda, koda açık ipuçları koyarak derleyiciye vb. beklenen yönü bildirebilirsin
    • Bu alanda çalışan biri değilim, sadece meraklıyım; ama dal tahmincileri her zaman o kadar iyi olmuş gibi görünüyor ki iki tarafı da yapmak değerli olmamış
      Modern CPU’ların komut yeniden sıralama tamponu yüzlerce komut derinliğinde ve bunların içinde yalnızca 8 koşullu sıçrama olsa bile programın gidebileceği yol sayısı 256 olur
      Dal tahmincisinin 8’inin tamamını doğru bilme olasılığı %50’den fazlaysa —ki gerçekten öyle— buna hazırlık için 256 kat iş yapmak değmez
    • Buna spekülatif yürütme denir ve hatırladığım kadarıyla tüm modern CPU’lar bunu yapıyor
      Daha fazla mikro-mimari durumu saklayacak silisyuma ve bu tekniği tam kullanacak daha fazla yürütme birimine ihtiyaç vardır. Ancak süperskaler CPU’larda, dallanması az kodda komut düzeyi paralelliğinden yararlanmak için bunlar zaten gerekli olduğu için mevcutlar
      Geri kalanı aliasing, kesmeler gibi karmaşık şeyleri ele alan baş ağrıtıcı işlerdir; ama donanım mühendisleri sihirbaz gibidir ve bunları da başarır
      Ancak spekülatif yürütme, cache zamanlama yan kanallarının kötüye kullanılmasıyla, yalnızca spekülatif olarak yürütülen ve mimari olarak yan etkileri commit edilmeyen kodun dokunduğu verilerden bilgi sızdırma olasılığını açar. Yani “gerçekte” yürütülmemiş koddan bile bilgi sızabilir
      Buna yetki denetimi gibi koşul kontrolleri nedeniyle açıkça yürütülmemiş kod da dahildir
      Tanıdık saldırı örneği Spectre’dır: https://en.m.wikipedia.org/wiki/Spectre_(security_vulnerabil...
    • Onlarca yıl önce zaten %90 doğruluk seviyesine ulaşılmıştı. İş yüküne bağlı olarak modern çipler çok daha iyi yapıyor
      Bu yüzden temelde hiç ekonomik değil. O çip kaynaklarını başka thread’lere veya çekirdeklere harcamak çok daha iyi
  • Bunun iyi bir fikir olup olmadığına karar vermek için önce performans verisi görmek isterim. Bu yaklaşımın dal tahmini cezası hakkında bilgi de yok
    Her hâlükârda bu yaklaşımın sezgisi, L1 komut cache’inde veya mikro-işlem cache’inde henüz bulunmayabilecek komutları agresif biçimde getirmek ve decode etmek gibi görünüyor
    Bu x86 için ve muhtemelen RISC-V için de önemli. İkisinde de komut uzunlukları değişken olduğu için, yalnızca komut cache bloğuna bakarak çekirdek o blok içindeki komutları nasıl decode edeceğini bilemez. Her iki ISA’da da bir komut cache bloğunu decode etmeye başlamak için en azından bir komutun PC’sini bilmek gerekir
    Bu yüzden uygulamanın iki blok ileride nereye zıplayabileceğini bilmek, mevcut yaklaşımdan daha ileriye kadar getirme ve decode etmede yardımcı olur
    Bu yaklaşım komut prefetching’e benzer, ancak komut prefetching çekirdeğe başlangıç noktası bilgisi vermez
    Yüksek performanslı ARM çekirdekleri, tüm komut uzunlukları 32 bit olduğu için muhtemelen “başlangıç noktası bulma” sorununu yaşamaz. Dolayısıyla başlangıç noktası bilinmese bile decode prosedürü paralelleştirilebilir
    Bu yöntemin, ön ucun ağırlıklı olduğu uygulamalara; örneğin sıcak kod bloklarının ikilinin çeşitli yerlerine dağılmış olduğu bulut iş yüklerine fayda sağlaması muhtemel. Diğer uygulama türlerinde performans kazancı mı yoksa kaybı mı olur, merak ediyorum

  • Hâlâ 2-ahead dal tahmincisinin ne olduğunu hiç bilmiyorum

    • Yazıda bağlantısı verilen eski araştırma makalesinden başlamak daha iyi olabilir
      Genel olarak eski araştırma makaleleri, okuyucunun bu tür konular hakkında çok daha az şey bildiğini varsayar. Çünkü o dönemde bu bilgi çok daha niş bir bilgiydi
  • Şu noktada gereken şey bellek bant genişliği. Tüketici sınıfı AM5 soketindeki 2 bellek kanalı, bu düzeydeki işlem performansına kıyasla, özellikle temel Apple Silicon ile karşılaştırıldığında bile sönük kalıyor.
    Ağır bir Zen yapılandırmasından M2 Max’e geçtim; bellek bant genişliğindeki artışın yoğun veri işlerini ne kadar hızlandırdığına yeniden şaşırdım. Oldukça ağır çoklu görevlerde bile Zen yapılandırmasının dar bellek hattı sık sık tıkanıyordu.

    • Gerçekte bellek bant genişliği darboğazına takılan ama CPU’nun GPU’dan daha uygun olduğu uygulama sayısı çok az.
      İnsanların özellikle LLM yüzünden Apple Silicon’a bakmasının nedeni, LLM’lerin GPU’ya daha uygun olması ama çok fazla VRAM de gerektirmesi ve NVIDIA’nın yüksek VRAM’li GPU’lara uçuk fiyatlar koyması.
      AMD gerçekten NVIDIA’nın hızını kesmek istiyorsa, 64~128 GB VRAM’li tüketici GPU’ları satmalı.
    • AM5’te aslında 4 bellek kanalı var. Çünkü DDR5 kanal sayısını ikiye katladı.