- CPython projesi yakın zamanda bayt kodu yorumlayıcısı için yeni bir uygulama stratejisi benimsedi. İlk sonuçlar, çeşitli platformlarda ortalama %10-15 performans artışı gösterdi
- Ancak bu performans artışı esas olarak LLVM 19'daki bir regresyon sorununu aşmanın sonucuydu. Daha iyi karşılaştırma temelleriyle (ör. GCC, clang-18, belirli ayar bayraklarına sahip LLVM 19) kıyaslandığında performans artışı %1-5'e düştü
Performans sonuçları
- Çeşitli derleyiciler ve yapılandırma seçenekleri kullanılarak CPython yorumlayıcısının birden çok derlemesi benchmark edildi. Testler Intel sunucusu ve Apple M1 Macbook Air üzerinde yapıldı.
- Tüm derlemelerde LTO ve PGO kullanıldı.
clang18 temel alınarak pypeformance/pyperf compare_to tarafından raporlanan ortalama kullanıldı.
- Derleyici performans karşılaştırması
- Apple M1 Macbook Air:
- clang18: temel
- clang19: 1.12 kat daha yavaş
- clang19.taildup: 1.02 kat daha yavaş
- clang19.tc: 1.00 kat daha yavaş
- gcc: N/A
- Kuyruk çağrısı yorumlayıcısı, clang-18 ile kıyaslandığında hâlâ hız artışı gösteriyordu, ancak clang-19'a geçildiğinde yaşanan yavaşlama daha çarpıcıydı.
LLVM regresyonu
Kısa arka plan
- Geleneksel bayt kodu yorumlayıcıları,
while döngüsü içindeki bir switch ifadesinden oluşur. Çoğu derleyici switch yapısını bir sıçrama tablosu olarak derler.
- Modern C derleyicileri, etiketlerin adresini alıp bunu "computed goto" olarak kullanma kalıbını destekler. CPython, kuyruk çağrısı çalışmasına kadar bu kalıbı kullanıyordu.
LLVM 19 regresyonu
- LLVM 19, tail-duplication geçişine sınırlamalar getirdi ve IR boyutu belirli bir eşiği aşarsa çoğaltmayı durdurdu. Bunun sonucu olarak CPython'da tüm dispatch sıçramaları birleştirildi ve computed
goto tabanlı uygulamanın amacı tamamen boşa çıktı.
Ek tuhaflıklar
- Kuyruk çağrısı çoğaltma mantığındaki değişikliğin regresyona yol açtığından emin olunuyor, ancak regresyonun boyutu tam olarak açıklanamıyor.
- Modern işlemcilerde %2-4 hız artışı daha yaygın kabul ediliyor.
Computed goto gerekli mi?
clang19.nocg benchmark'ı, clang19'dan daha hızlı olduğunu iddia ediyor. Bu, derleyicinin switch tabanlı yorumlayıcı kullanarak aynı optimizasyonu yapabildiğini gösteriyor.
Düzeltme
- LLVM pull request 114990 bu regresyonu düzeltti. Bu düzeltme beklenen performansı geri getiriyor.
Değerlendirmeler
Benchmarking üzerine
- Sistem optimizasyonunda benchmark'lar ve benchmarking metodolojisi oluşturulur, ardından önerilen değişiklikler değerlendirilir.
- Benchmark'lar, belirli veri noktalarını genellemek için daha fazla varsayım ve kabule ihtiyaç duyar.
Temel karşılaştırma çizgisi
- Yeni bir çözüm veya yöntem önerildiğinde, bunu "şu anda bilinen en iyi yaklaşım" ile karşılaştırmak yaygındır.
Yazılım mühendisliği üzerine
- Yazılım sistemleri karmaşık, birbirine bağlı ve hızla değişen yapılardır.
- Optimize edici derleyiciler, programcının niyetine saygı gösterirken kodu da optimize etmek zorunda oldukları için bir gerilim içinde çalışır.
Optimize edici derleyiciler
musttail niteliği, optimizasyonla ilgili yeni bir derleyici özelliği türünü temsil eder. Bu, performansa duyarlı kod yazmak için daha güçlü bir stil sunabilir.
nix hakkında bir not daha
nix bu projede çok yararlı oldu. Birden çok Python yorumlayıcısı sürümünü yönetmek ve derlemek için büyük kolaylık sağladı.
1 yorum
Hacker News görüşleri
Merhaba. CPython'a tail-calling interpreter ekleyen PR'ın yazarıyım
Benchmark yapmak gerçekten çok zor bir iş
Yazarın bu sorunun gerçeğini ortaya çıkarmasını takdir ediyorum
Bu, C'nin "makineye yakın" bir dil olmadığının iyi bir örneği
Derleyicinin döngüleri düzenleme biçimini ayarlaması nedeniyle tail-call interpreter duyurulduğu kadar etkili değil
Python build'lerinin performansını değerlendirmek çok zor
İlgili tartışmalar:
Harika bir yazı
Kısa süre önce Python 3.9'dan 3.13'e kadar benchmark yaptım
Bu tür bir optimizasyonun tail-call optimization ile nasıl ilişkili olduğunu merak ediyorum