Ruby / Python gibi dinamik bir dil C / C ++ benzeri performansa ulaşabilir mi?


64

Ruby / C + C ++ ile benzer ve karşılaştırılabilir bir performansa sahip Ruby gibi dinamik diller için derleyiciler oluşturmak mümkün olup olmadığını merak ediyorum? Derleyiciler hakkında anladığım kadarıyla, Ruby'yi almak, Ruby kodunu derlemek hiç etkili olamaz çünkü Ruby'nin yansıma işlemlerini yapma biçimi, tamsayıdan büyük tamsayıya otomatik tür dönüştürme gibi özellikler ve statik yazı yazma eksikliği verimli bir derleyici oluşturmayı sağlar Ruby için son derece zor.

Ruby veya diğer dinamik dilleri C / C ++ 'a çok yakın bir şekilde çalışan bir ikili dosyada derleyebilecek bir derleyici oluşturmak mümkün mü? PyPy / Rubinius gibi JIT derleyicilerinin sonuçta C / C ++ ile eşleşmemesinin veya hiç eşleşmemesinin temel bir nedeni var mı?

Not: “Performansın” belirsiz olabileceğini anlıyorum, bu yüzden şunu söylemek gerekirse, eğer C / C ++ 'da X'i Y ile yapabilirseniz, Ruby / Python'da X'i Y'ye yakın bir performansla yapabilir misiniz? X, aygıt sürücülerinden ve işletim sistemi kodlarından web uygulamalarına kadar her şeydir.


1
Soruyu tekrar ifade edebilir misiniz? Böylece başkalarına göre uygun kanıtlarla desteklenen cevapları teşvik edebilir misiniz?
Raphael

@Raphael Ben devam ettim ve değiştirdim. Sanırım düzenlemem sorunun anlamını değiştirmiyor, ancak fikir parçalarını daha az davet ediyor.
Gilles

1
Özellikle, bir (veya birkaç) somut performans ölçüsünü düzeltmeniz gerektiğini düşünüyorum . Çalışma süresi? Alan kullanımı? Enerji kullanımı? Geliştirici zamanı? Yatırımın geri dönüşü? Ayrıca, bu soruyu ilgilendiren metamızdaki bu soruyu (veya daha doğrusu cevaplarını) not edin.
Raphael

Bu soru, dinsel savaşların tipik bir başlatıcısıdır. Ve cevaplardan görebileceğimiz gibi, çok medeni bir cevap olsa da bir tane alıyoruz.
Andrej Bauer

İsteğe bağlı tür açıklamalara izin veren dinamik diller vardır (örneğin: Clojure). Benim bildiğim kadarıyla, açıklamalı fonksiyonlarla ilişkili performans, bir dilin statik olarak ne zaman yazılacağına eşdeğerdir.
Pedro Morte Rolo

Yanıtlar:


68

“Evet” diyen herkese, cevabın tasarım gereği “hayır” olduğu konusunda bir teklif sunacağım . Bu diller , statik olarak derlenmiş dillerin performansını asla karşılayamaz .

Kos, (çok geçerli) dinamik dillerin çalışma zamanında sistem hakkında daha fazla bilgi sahibi olduğu ve kodu optimize etmek için kullanılabileceği noktasını sundu.

Ancak, madalyonun başka bir tarafı var: bu ek bilgilerin takip edilmesi gerekiyor. Modern mimarilerde bu bir performans katilidir.

William Edwards , tartışmaya güzel bir genel bakış sunar .

Özellikle, Kos bahsettiği optimizasyon çok sınırlı kapsamı dışında uygulanamaz sürece oldukça büyük ölçüde dillerin ifade gücünü sınırlayan Devin tarafından belirtildiği gibi,. Bu elbette uygun bir takastır, ancak tartışma uğruna, dinamik bir dil değil, statik bir dille karşılaşırsınız. Bu diller temel olarak Python veya Ruby'den farklıdır, çünkü çoğu insanın anlayacağı gibi.

William, bazı ilginç IBM slaytlarından bahsediyor :

  • Her değişken dinamik olarak yazılabilir: Tip kontrolleri gerekir
  • Her ifade, tür uyuşmazlığı vb. Nedeniyle potansiyel olarak istisnalar ortaya koyabilir: İstisna kontrolleri gerekli
  • Her alan ve sembol çalışma zamanında eklenebilir, silinebilir ve değiştirilebilir: Erişim kontrolü gerekir
  • Her nesnenin türü ve sınıf hiyerarşisi çalışma zamanında değiştirilebilir: Sınıf hiyerarşi kontrolleri gerekir

Bazıları bu denetimlerin analizi sonrasında ortadan kaldırılabilir (NB: Bu analiz de zaman alır - zamanında).

Ayrıca Kos, dinamik dillerin C ++ performansını bile geçebileceğini savunuyor. JIT gerçekten programın davranışını analiz edebilir ve uygun optimizasyonları uygulayabilir.

Ancak C ++ derleyicileri de aynı şeyi yapabilir! Modern derleyiciler, uygun girdi verilirse program çalışma zamanı davranışını modelleyebilen ve bir JIT'in uygulayacağı optimizasyonları uygulayabilen profil kılavuzlu optimizasyon sunar.

Tabii ki, bunlar gerçekçi eğitim verilerinin varlığına dayanıyor ve ayrıca kullanım şekli ortada değişirse, program çalışma zamanı özelliklerini uyarlayamaz. JIT'ler teorik olarak bunun üstesinden gelebilir. Optimizasyonları değiştirmek için JIT’in sürekli olarak yürütmeyi yavaşlatan kullanım verilerini toplamak zorunda kalacağından, uygulamada bu ücretlerin nasıl uygulanacağını görmek isterim.

Özetle, çalışma zamanı hot-spot optimizasyonlarının , statik analiz ve optimizasyona kıyasla uzun vadede izleme çalışma zamanı bilgilerinin ek yükünden daha ağır olduğuna ikna olmadım .


2
@Raphael O zaman bu derleyicinin bir “eksikliği”. Özellikle, javacprofil güdümlü optimizasyon hiç oldu mu? Bildiğim kadarıyla değil. Genel olarak bir JITted dilinin derleyicisini en iyi duruma getirme konusunda mantıklı gelmez, çünkü JIT bunu başarabilir (ve en azından, bu şekilde daha fazla dil çabadan faydalanır). Bu yüzden (anlaşılır şekilde) javac, bildiğim kadarıyla , optimizer için hiçbir zaman çok çaba sarf edilmedi (.NET dilleri için bu kesinlikle doğrudur).
Konrad Rudolph

1
@Raphael Anahtar kelime: belki. Her iki şekilde de göstermiyor. Tüm söylemek istediğim buydu. Önceki paragraflardaki varsayımım için nedenler (ancak kanıt yok) verdim.
Konrad Rudolph

1
@Ben karmaşık olduğunu inkar etmiyorum. Bu sadece bir sezgidir. Tüm bu bilgileri çalışma zamanında izlemek, sonuçta pahasına geliyor. IO hakkındaki düşüncene ikna olmadım. Bu tahmin edilebilir ise (= tipik kullanım durumu), PGO bunu tahmin edebilir. Sahte ise, JIT’in de bunu optimize edebileceğine ikna olmadım. Belki arada bir, tamamen şanssız. Ama güvenilir? …
Konrad Rudolph

2
@Konrad: Sezginiz yanlış. Çalışma zamanında değişken olmakla ilgili değil , derleme zamanında tahmin edilemezlikle ilgili . JIT'ler için statik optimizasyonun tatlı noktası, programın davranışının profilleme için "çok hızlı" çalışma zamanında değişmesi değil, programın davranışının programın her bir çalışmasında optimize edilmesi kolay olduğu, ancak çılgınca değişiklik gösterdiği zaman koşar. Statik bir optimizasyon cihazının genellikle yalnızca bir koşul kümesi için optimizasyon yapması gerekir; oysa bir JIT, bu çalışmada meydana gelen koşullar için her bir çalışmayı ayrı ayrı optimize eder.
Ben

3
Uyarı: Bu yorum dizisi küçük bir sohbet odasına dönüşüyor. Bu tartışmaya devam etmek isterseniz, lütfen sohbete gönderin. Yorumlar, asıl gönderiyi geliştirmek için kullanılmalıdır. Lütfen bu konuşmayı burada sonlandırın . Teşekkürler.
Robert Cartaino

20

X ile C / C ++ 'ta X yapabilirseniz, Y'ye yakın performansla Ruby / Python'da X yapabilir misiniz?

Evet. Örnek olarak PyPy'i ele alalım. Yorum yaparken C'ye yakın performans gösteren bir Python kodu koleksiyonudur (hepsi bu kadar yakın değil, her ikisi de çok da uzak değil). Bu her değişkene statik türü atamak için kaynak kodu üzerinde tam bir program analizi yaparak (görüyor mu Annotator ve Rtyper detaylar için docs) ve sonra, bir kez C vermek aynı tip bilgilerle donanmış, aynı gerçekleştirebilirsiniz optimizasyon türleri. En azından teoride.

Elbette ki takas, yalnızca bir Python kodu alt kümesi RPython tarafından kabul edilir ve genel olarak, bu kısıtlama kaldırılmış olsa bile, yalnızca bir Python kodu alt kümesi iyi yapabilir: analiz edilebilir ve statik tipler verilen alt küme.

Python'u yeterince kısıtlarsanız, kısıtlanmış alt kümeden faydalanıp verimli bir kod oluşturacak şekilde optimize ediciler oluşturulabilir. Bu gerçekten ilginç bir fayda değil, aslında iyi bilinmektedir. Ancak Python'u (veya Ruby'yi) ilk başta kullanmanın amacı, belki de iyi analiz etmeyen ve iyi performansla sonuçlanan ilginç özellikler kullanmak istedik! Yani ilginç soru aslında ...

Ek olarak, PyPy / Rubinius gibi JIT derleyicileri performansta C / C ++ ile eşleşecek mi?

Hayır.

Demek istediğim: elbette, kod çalıştırıldığında, kodun tamamı makine koduna kadar derlenecek kadar yazım bilgisi ve yeterli sıcak nokta alabilirsiniz. Belki bazı kodlar için C'den daha iyi performans göstermesini sağlayabiliriz. Bunun çok tartışmalı olduğunu sanmıyorum. Ancak yine de “ısınması” gerekir ve performans hala biraz daha az öngörülebilirdir ve tutarlı ve tahmin edilebilir şekilde yüksek performans gerektiren belirli görevler için C veya C ++ kadar iyi olmaz.

Python veya Ruby'den daha fazla tür bilgisine sahip olan ve Python veya Ruby'den daha iyi geliştirilmiş bir JIT derleyicisine sahip olan Java için mevcut performans verileri hala C / C ++ ile eşleşmiyor. Ancak, aynı oyunda.


1
"Elbette ki takas, yalnızca bir Python kodunun bir alt kümesinin kabul edilebilir olması veya daha doğrusu sadece bir Python kodunun bir alt kümesinin iyi yapabileceğidir: analiz edilebilecek ve statik tipler verilen alt küme." Bu tam olarak doğru değil. Sadece altküme RPython derleyicisi tarafından kesinlikle kabul edilebilir. RPython'a makul derecede verimli C derleme, yalnızca Python'un derlenmesi zor parçalarının RPython programlarında asla oluşmayacağının garantilenmesi nedeniyle tam olarak çalışır; bu yalnızca ortaya çıkarlarsa optimize edilmeyecekleri anlamına gelmez. Tüm Python'u kullanan derlenmiş tercüman.
Ben

1
JIT hakkında: Java'nın C (++) lezzetlerini aştığı birden fazla kriter gördüm. Sadece C ++ ile artırma, güvenilir bir şekilde önde görünüyor. Bu durumda, geliştirici zamanı başına performans hakkında merak ediyorum, ancak bu başka bir konudur.
Raphael

@Ben: Bir kez RPython'a sahip olduğunuzda, RPython derleyicisi başarısız olduğunda CPython yorumlayıcısını kullanmaya geri dönen bir derleyici / tercüman oluşturmak çok önemlidir, bu nedenle "yalnızca bir Python kodu alt kümesi iyi yapabilir: ..." tamamen doğrudur.
Yalan Ryan

9
@Raphael İyi yazılmış C ++ kodunun Java'dan daha iyi performans gösterdiği birçok kez gösterilmiştir . C ++ 'a girmesi biraz daha zor olan "iyi yazılmış" kısım, bu yüzden birçok bankta Java'nın C ++' dan daha iyi sonuçlar aldığını görüyorsunuz. C ++ bu nedenle, daha pahalıdır, ancak sıkı mem kontrolü ve metal kumuna ihtiyaç duyulduğunda, C / C ++, döndüğünüz şeydir. Özellikle C sadece ac / p birleştiricisidir.
TC1

7
Diğer dillerin azami performansını C / C ++ gibi dillerle karşılaştırmak, kolay anlaşılır bir alıştırmadır. Makinenin herhangi bir dilde yazılmış bir programı çalıştırmak için yapabileceği herhangi bir şey varsa, derhal çalıştırılan talimatların izinden derleme yazarak çoğaltabilirsiniz. @Raphael'in daha önce yorumladığı gibi, geliştirme çabası başına performans (çalışma saatleri, kod satırları vb.) Gibi çok daha ilginç bir ölçüm olacaktır.
Patrick87

18

Kısa cevap: bilmiyoruz , 100 yıl sonra tekrar sorun. (O zaman hala bilmiyor olabiliriz; muhtemelen asla bilemeyiz.)

Teorik olarak, bu mümkün. Yazılan tüm programları alın, el ile onları mümkün olan en verimli makine koduna çevirin ve kaynak kodları makine kodlarıyla eşleştiren bir tercüman yazın. Bu, yalnızca sınırlı sayıda program yazılan bir program olduğundan mümkündür (ve daha fazla program yazılırken el ile çevirileri sürdürün). Bu, elbette pratik olarak tamamen aptalcadır.

O zaman yine teoride, üst düzey diller makine kodunun performansına ulaşabilir, ancak bunu geçemezler. Bu hala çok teorik, çünkü pratik açıdan, nadiren makine koduna başvuruyoruz. Bu argüman üst seviye dilleri karşılaştırmak için geçerli değildir: C'nin Python'dan daha verimli olması gerektiği anlamına gelmez, sadece bu makine kodunun Python'dan daha kötü yapamayacağı anlamına gelir.

Diğer taraftan, yalnızca deneysel terimlerle, çoğu zaman , yorumlanmış yüksek seviye dillerin derlenmiş düşük seviye dillerden daha kötü performans gösterdiğini görebiliriz. Zamanında hassas olmayan kodları, çok yüksek seviyeli dillerde ve montajda zaman açısından kritik iç döngülerde, C ve Python gibi diller arasına giren dillerde yazma eğilimindeyiz. Bunu destekleyecek istatistiklere sahip olmasam da, çoğu durumda bunun gerçekten en iyi karar olduğunu düşünüyorum.

Bununla birlikte, üst düzey dillerin gerçekçi bir şekilde yazacakları kodu attığı tartışmasız örnekler vardır: özel amaçlı programlama ortamları. Matlab ve Mathematica gibi programlar, bazı matematik problemlerini çözmede, ölümlülerin yazabileceğinden çok daha iyidir. Kütüphane fonksiyonları C veya C ++ dilinde yazılmış olabilir (“düşük seviyeli diller daha verimlidir” kampına doğru yakıttır), ancak Mathematica kodunu yazdığımda bu benim işim değil, kütüphane kara bir kutu.

Teorik olarak Python'un C'ye göre en iyi performansa yaklaşması veya hatta yaklaşması mümkün mü? Yukarıda görüldüğü gibi, evet, ama bugün bundan çok uzaktayız. Sonra tekrar, derleyiciler geçen yıllarda çok fazla ilerleme kaydetti ve bu ilerleme yavaşlamadı.

Üst düzey diller daha çok şeyi otomatik hale getirme eğilimindedir, bu nedenle gerçekleştirecek daha çok işi vardır ve bu nedenle daha az verimli olma eğilimindedirler. Öte yandan, daha fazla anlamsal bilgilere sahip olma eğilimindedirler, bu nedenle optimizasyonları belirlemek daha kolay olabilir (eğer bir Haskell derleyici yazarsanız, başka bir dişlinin burnunuzun altındaki bir değişkeni değiştireceği konusunda endişelenmenize gerek yoktur). Elmaları ve portakalları farklı programlama dilleri ile karşılaştırmak için harcanan çabalardan biri Bilgisayar Dili Kıyaslama Oyunu (eskiden çatışmada olarak bilinen). Fortran, sayısal görevlerde parlama eğilimindedir; Ancak, yapılandırılmış veriyi veya yüksek oranlı iplik komutasyonunu değiştirmek söz konusu olduğunda, F # ve Scala iyi yapıyor. Bu sonuçları müjdeci olarak almayın: ölçtüklerinin çoğu her dilde test programının yazarının ne kadar iyi olduğu.

Üst düzey dillerin lehine olan bir argüman, modern sistemlerdeki performansın, yürütülen talimatların sayısıyla çok fazla ilişkili olmadığı ve zaman içinde daha az olduğu anlamına gelir. Düşük seviyeli diller, sıralı makineler için iyi eşleşmelerdir. Üst düzey bir dil iki kat daha fazla komut yürütürse, ancak önbelleği daha akıllıca kullanmayı başarırsa, bu nedenle önbellek özünün yarısı kadarını yapar, kazananı sonlandırabilir.

Sunucu ve masaüstü platformlarında, CPU'lar daha hızlı alamadıkları bir platoya neredeyse ulaştı (mobil platformlar da oraya geliyor); bu, paralelliğin sömürülmesinin kolay olduğu dilleri desteklemektedir. Birçok işlemci zamanlarının çoğunu bir G / Ç yanıtını bekleyerek geçirir; Hesaplamada harcanan zaman, G / Ç miktarı ile karşılaştırıldığında çok önemli değildir ve programcının iletişimi en aza indirmesini sağlayan bir dil avantajlıdır.

Sonuçta, üst düzey diller bir ceza ile başlarken, iyileştirme için daha fazla alan var. Ne kadar yaklaşabilirler? 100 yıl sonra tekrar sor.

Son not: Sık sık, karşılaştırma A dilinde yazılabilecek en verimli program ile B dilinde aynı olan veya her dilde yazılan en verimli program arasında değil , aynı zamanda yazılabilecek en verimli program arasındadır . belirli bir süre içinde bir insan tarafından her dilde . Bu, prensipte bile matematiksel olarak analiz edilemeyen bir elementi ortaya koymaktadır. Pratik açıdan, bu, en iyi performansın, performans hedeflerine ulaşmak için ne kadar düşük seviyeli kod yazmanız gerektiği ve yayınlanma tarihlerini karşılamak için ne kadar düşük seviyeli kod yazmanız gerektiği arasında bir uzlaşma olduğu anlamına gelir.


Bence yüksek ve düşük seviye arasındaki ayrım yanlış. C ++ (çok) yüksek olabilir. Yine de modern, yüksek seviye C ++ (zorunlu olarak) düşük seviye eşdeğerinden daha kötü performans göstermez - tam tersine. C ++ ve kütüphaneleri, performans kesintisi olmadan üst düzey soyutlamalar sunmak için dikkatlice tasarlandı . Aynısı Haskell örneğiniz için de geçerli: yüksek seviyeli soyutlamaları çoğu zaman optimizasyonları önlemek yerine mümkün kılar. Dinamik diller ve statik diller arasındaki orijinal ayrım bu konuda daha anlamlı.
Konrad Rudolph

@KonradRudolph Haklısın, bu düşük seviye / yüksek seviye biraz keyfi bir ayrımdır. Ancak dinamik vs statik diller de her şeyi yakalamaz; Bir JIT farkın çoğunu ortadan kaldırabilir. Temel olarak, bu sorunun bilinen teorik cevapları önemsiz ve yararsızdır ve pratik cevap “bağlıdır” dır.
Gilles

Öyleyse, bence “JIT'ler ne kadar iyi olabilir ve statik derlemeyi üstlenirlerse, statik olarak derlenmiş diller de onlardan yararlanabilir mi?” Sorusu en azından JIT'leri hesaba kattığımızda soruyu böyle anlıyorum. Ve evet, değerlendirmenize katılıyorum ama elbette “bağlı” nın ötesine geçen bazı bilinçli tahminler alabiliriz. ;-)
Konrad Rudolph

@KonradRudolph Tahmin etmek istesem, Yazılım Mühendisliği'ni rica ediyorum .
Gilles

1
Dil atışları maalesef niceliksel ölçütler için sorgulanabilir bir kaynaktır: sadece dilin tipik olduğu düşünülen programları kabul etmemektedir. Bu aldatıcı ve öznel bir gerekliliktir; Bu, bir atış çatışması uygulamasının aslında herhangi bir yarar olduğunu kabul edemezsiniz (ve pratikte, bazı uygulamalar açıkça reddedilmiş üstün alternatiflere sahiptir). Diğer tarafda; bunlar mikrobeneklerdir ve bazı uygulamalar sadece performansı kazanmak için daha normal bir senaryoda asla göz önünde bulundurmayacağınız olağandışı teknikleri kullanır. Yani: bu bir oyun, çok güvenilir bir veri kaynağı değil.
Eamon Nerbonne

10

C ++ deyimi arasındaki temel fark x = a + bve Python deyimi x = a + bbir C / C ++ derleyicisi bu ifadeden anlatmak (ve türleri hakkında hazır olduğunu biraz ekstra bilgi olmasıdır x, ave btam olarak ne makine kodu ihtiyacı yürütülecek) . Python ifadesinin hangi işlemleri yapacağını söylemek için Halting Problemini çözmeniz gerekir.

C'de bu ifade temelde birkaç makine ekleme türünden birini derleyecektir (ve C derleyicisi hangisini bilir). C ++ 'da bu şekilde derlenebilir ya da statik olarak bilinen bir işlevi çağırmak için derlenebilir ya da (en kötü durumda) sanal bir yöntem arama ve çağrısı derlemek zorunda kalabilir, ancak bunun bile oldukça küçük bir makine kodu vardır. Daha da önemlisi, C ++ derleyicisi tek bir hızlı toplama işlemi yapıp yapamayacağını veya daha yavaş seçeneklerden birini kullanması gerekip gerekmediğini statik olarak bilinen tiplerden anlayabilir.

O takdirde Python'da, derleyici teorik neredeyse o kadar iyi yapabileceğini biliyordu o ave bher ikisi de intbu. Bazı ilave ek yükler var, ancak türler statik olarak biliniyorsa, muhtemelen bundan da kurtulabilirsiniz (tamsayıların yöntemleri olan nesneler, süper sınıfların hiyerarşisi, vs.). Sorun Python'un yapabileceği bir derleyici değilBunu bilirsiniz, çünkü çalışma zamanında sınıflar tanımlanır, çalışma zamanında değiştirilebilir ve hatta tanımlamayı ve içe aktarmayı yapan modüller bile çalışma zamanında çözülür (ve hangi ithalat ifadelerinin çalıştırıldığı bile sadece çalışma zamanında bilinen şeylere bağlıdır). Bu yüzden Python derleyicisi derlenecek ifadenin ne yapacağını bilmek için hangi kodun yürütüldüğünü bilmek zorundadır (örn. Halting Problemini çözmek).

Dolayısıyla, teorik olarak mümkün olan en karmaşık analizlerde bile, verilen bir Python ifadesinin vaktinden önce ne yapacağını söyleyemezsiniz. Bu, karmaşık bir Python derleyicisi uygulanmış olsa bile, hemen hemen her durumda bir nesnenin sınıfını belirlemek ve yöntemleri bulmak için (sınıf hiyerarşisinin MRO'sunu geçen, Python sözlük arama protokolünü izleyen makine kodunu çıkarması gerektiği anlamına gelir) bu da çalışma zamanında dinamik olarak değişebilir ve bu nedenle basit bir sanal yöntem tablosuna derlemek zordur) ve temelde (yavaş) tercümanların yaptıklarını yapar. Bu nedenle, dinamik diller için gerçekten karmaşık bir optimizasyon derleyicisi bulunmuyor. Sadece bir tane oluşturmak zor değil, mümkün olan en yüksek kazanç

Bu hangi kodun dayalı unutmayın edilir , bu kodu nedir dayanıyor yapıyor olabilir yapıyor. Basit bir tamsayı aritmetik işlem dizisi olan Python kodu bile , rasgele sınıf işlemlerini başlatıyormuş gibi derlenmelidir . Statik diller, kodun neler yapabileceği konusunda daha büyük kısıtlamalara sahiptir ve sonuç olarak derleyicileri daha fazla varsayım yapabilir.

JIT derleyicileri bu süreyi derleyip / optimize etmek için çalışma zamanına kadar bekleyerek kazanır. Bu onlara kod ne için çalışır kodu yayarlar sağlar edilir o yapıyor olabilir olandan ziyade yapıyor. Bu nedenle, JIT derleyicileri, dinamik diller için statik dillerden çok daha büyük bir potansiyel kazancına sahiptir; Daha statik diller için, bir optimizatörün bilmek istediklerinin çoğu önceden bilinir, bu nedenle daha sonra en iyi duruma getirerek JIT derleyicisinin yapması için daha az şey bırakabilirsiniz.

Dinamik diller için, derlenmiş ve optimize edilmiş C / C ++ ile karşılaştırılabilir yürütme hızları elde ettiğini iddia eden çeşitli JIT derleyicileri vardır. Herhangi bir dil için önceden yapılmış bir derleyici tarafından yapılamayan bir JIT derleyicisi tarafından yapılabilecek optimizasyonlar bile vardır, bu nedenle teorik olarak JIT derlemesi (bazı programlar için) bir gün mümkün olan en iyi statik derleyiciden daha iyi performans gösterebilir. Ancak Devin'in doğru bir şekilde belirttiği gibi, JIT derlemesinin özellikleri (yalnızca "sıcak noktalar" hızlıdır ve yalnızca bir ısınma süresinden sonradır), JIT tarafından derlenen dinamik dillerin, tüm olası uygulamalar için uygun olma ihtimalinin düşük olduğu anlamına gelir. genellikle statik olarak derlenmiş dillerden daha hızlı veya daha hızlı.


1
Bu şimdi yorum yapmayan iki aşağı oy. Bu cevabın nasıl geliştirileceğine dair önerilerimi memnuniyetle karşılarım!
Ben

Oy vermedim ama “durma problemini çözme ihtiyacı” konusunda yanılıyorsun. Birçok durumda, dinamik dillerdeki kodun optimal hedef koda derlenebileceği gösterilmiştir, oysa ki bu gösterilerden hiçbiri durma sorununa bir çözüm
getirmedi

@mikera Üzgünüm, ama hayır, yanılıyorsun. Hiç kimse, tamamen genel Python veya diğer dinamik diller için bir derleyici (GCC'nin bir derleyici olduğunu anlamış olduğumuz anlamında) uygulamamıştır . Bu tür her sistem, yalnızca bir dilin alt kümesi için çalışır, veya yalnızca belirli programlar için çalışır veya bazen temel olarak sabit kodlanmış bir program içeren bir tercüman olan kod yayar. İsterseniz foo = x + y, derleme zamanında toplama operatörünün davranışını tahmin etmenin durma problemini çözmeye bağlı olduğu satırı içeren bir Python programı yazacağım .
Ben

Haklıyım ve konuyu kaçırdığınızı düşünüyorum. "Pek çok durumda" dedim. "Mümkün olan her koşulda" demedim. Durma problemine bağlı olarak tartışmalı bir örnek oluşturabilecek olsanız da olmasanız da, gerçek dünyada büyük oranda önemsizdir. FWIW, C ++ için de benzer bir örnek oluşturabilirsin, böylece hiçbir şey ispatlamazdın. Her neyse, buraya cevabınıza iyileştirmeler önermek için, tartışmaya girmeye gelmedim. Al ya da git.
mikera

@mikea Konuyu kaçırmış olabileceğinizi düşünüyorum. Derlemek amacıyla x + yverimli makine ilavesi operasyonlarına, bunun olup olmadığını derleme zamanında bilmek gerekir. Her zaman , sadece zamanın değil. Dinamik diller için, gerçekçi sezgiler çoğu zaman doğru tahmin edilse de, gerçekçi programlarla bu neredeyse hiçbir zaman mümkün değildir. Derleme, derleme zamanı garantileri gerektirir . Yani "birçok durumda" hakkında konuşarak aslında cevabımı hiç cevaplamıyorsunuz.
Ben

9

Dinamik diller için en kötü senaryoyu ana hatlarıyla gösteren hızlı bir gösterici:

Perl ayrıştırma hesaplanabilir değil

Sonuç olarak, (dolu) Perl hiçbir zaman statik olarak derlenemez.


Genel olarak, her zaman olduğu gibi, bağlıdır. Dinamik özellikleri statik olarak derlenmiş bir dilde taklit etmeye çalışırsanız, iyi düşünülmüş tercümanlar veya (kısmen) derlenmiş değişkenlerin, statik olarak derlenmiş dillerin performansının yakına veya düşük performans gösterebileceğine inanıyorum.

Akılda tutulması gereken bir başka nokta, dinamik dillerin C'den başka bir sorunu çözdüğüdür. C, assembler için hoş sözdiziminden çok daha fazladır, dinamik diller ise zengin soyutlamalar sunar. Çalışma zamanı performansı genellikle öncelikli bir mesele değildir: örneğin, pazara sunma süresi, geliştiricilerin kısa süre içinde karmaşık, yüksek kaliteli sistemler yazabilmelerine bağlıdır. Yeniden derleme olmadan genişletilebilirlik, örneğin eklentileri ile, başka bir popüler özellik. Bu durumlarda hangi dili tercih edersiniz?


5

Bu soruya daha nesnel bir bilimsel cevap sunma çabasında, şöyle iddia ediyorum. Dinamik bir dil, çalışma zamanında karar vermek için bir tercüman veya çalışma zamanı gerektirir. Bu tercüman veya çalışma zamanı bir bilgisayar programıdır ve bu nedenle bazı programlama dillerinde statik veya dinamik olarak yazılmıştır.

Tercüman / çalışma zamanı statik bir dilde yazılmışsa, o zaman (a) yorumladığı dinamik programla aynı işlevi gerçekleştiren ve (b) en az aynı anda gerçekleştiren statik dilde bir program yazılabilir. Umarım, bu açıktır, çünkü bu iddiaların kesin bir kanıtını sağlamak ek (muhtemelen kayda değer) çaba gerektirecektir.

Bu iddiaların doğru olduğu varsayıldığında, yorumlamanın / çalışma zamanının dinamik bir dilde de yazılması gerekir. Bununla birlikte, daha önce olduğu gibi aynı sorunla karşı karşıyayız: tercüman dinamikse, dinamik veya statik bir programlama dilinde yazılmış olması gereken bir tercüman / çalışma zamanı gerektirir.

Bir tercüman örneğinin çalışma zamanında kendini yorumlayabildiğini varsaymadığınız sürece (umarım bu açıkça saçmadır), statik dilleri geçmenin tek yolu her tercüman örneğinin ayrı bir tercüman örneği tarafından yorumlanmasıdır; bu, ya sonsuz bir gerileme (umarım ki bu açıkça apaçık saçmadır) ya da kapalı bir tercüman döngüsüne yol açar (umarım bu da açıkça saçmadır).

Öyleyse, teoride bile, dinamik dillerin genel olarak statik dillerden daha iyi performans göstermediği görülmektedir. Gerçekçi bilgisayarların modellerini kullanırken, daha da mantıklı görünüyor; sonuçta, bir makine sadece makine talimat dizilerini çalıştırabilir ve makine talimatlarının tüm dizileri statik olarak derlenebilir.

Uygulamada, dinamik bir dilin performansını statik bir dil ile eşleştirmek, yorumlayıcının / çalışma zamanını statik bir dilde yeniden uygulamanızı gerektirebilir; Ancak, bunu yapabileceğinize göre bu argümanın noktası ve noktasıdır. Bu bir tavuk ve yumurta sorusudur ve yukarıda yapılan kanıtlanmamış (benim görüşüme göre, çoğunlukla açık) varsayımlara katılsanız bile, aslında buna cevap verebiliriz; başını, dinamik değil, statik dillere vermeliyiz.

Bu tartışmanın ışığında soruyu cevaplamanın başka bir yolu şudur: depolanan programda, kontrol = modern hesaplamanın merkezinde yatan hesaplama veri modeli, statik ve dinamik derleme arasındaki fark yanlış bir ikiliktir; Statik olarak derlenmiş diller çalışma zamanında rasgele kod üretme ve yürütme araçlarına sahip olmalıdır. Temelde evrensel hesaplama ile ilgilidir.


Bunu tekrar okuyarak, doğru olduğunu sanmıyorum. JIT derlemesi tartışmanızı bozuyor. Hatta en basit kod, örneğin main(args) { for ( i=0; i<1000000; i++ ) { if ( args[0] == "1" ) {...} else {...} }olabilir belirgin değeri bir kez hızlandırdı argsbilinmektedir (bunu varsayarak biz iddia mümkün olabilir ki, hiç değişmez). Statik bir derleyici, karşılaştırmayı hiç bırakmayan bir kod oluşturamaz. (Tabii ki, bu örnekte sadece ifdöngü dışına çekersiniz. Ama şey daha sarsılmış olabilir.)
Raphael

@Raphael ben JIT muhtemelen düşünüyorum yapar benim argüman. JIT derlemesi yapan programlar (örneğin, JVM) tipik olarak statik olarak derlenmiş programlardır. Statik olarak derlenmiş bir JIT programı bir betiği diğer statik programlardan daha hızlı çalıştırabilirse, betiği JIT derleyicisiyle "paketleyin" ve paketine statik olarak derlenmiş bir program çağırın. Bu, en azından JIT'in daha iyi yapması gereken herhangi bir iddiaya aykırı bir biçimde, ayrı bir dinamik programda çalışan JIT'in yapması gerekir.
Patrick87,

Hm, bir Ruby betiğini tercümanı ile donatmak size statik olarak derlenmiş bir program sunuyor demek gibi bir şey. Kabul etmiyorum (bu konuda dillerin tüm ayrımlarını ortadan kaldırdığı için), ancak bu kavramlar değil anlambilim meselesidir. Kavramsal olarak, programı çalışma zamanında (JIT) uyarlamak, derleme zamanında (statik derleyici) yapamayacağınız optimizasyonları yapabilir ve bu benim açımdan.
Raphael

@Raphael Anlamlı bir ayrımın olmadığı, cevabın bir nevi noktasıdır: bazı dilleri katı bir şekilde statik olarak sınıflandırma girişimi ve dolayısıyla performans sınırlamalarından muzdarip olmaları, tam olarak bu nedenle başarısız olur: önceden paketlenmiş (Ruby) arasında zorlayıcı bir fark yoktur. , script) paket ve bir C programı. (Ruby, script), makinenin belirli bir sorunu etkin bir şekilde çözmek için doğru talimat sırasını çalıştırmasını sağlayabilirse, akıllıca hazırlanmış bir C programı olabilir.
Patrick87,

Ama yapabilirsiniz farkı tanımlar. Bir değişken eldeki kodu işlemciye (C), diğeri ise çalışma zamanında derler (Ruby, Java, ...). Birincisi "statik derleme" ile kastettiğimiz şeydir, ikincisi "tam zamanında derleme" olur (verilere bağlı optimizasyonlara izin verir).
Raphael

4

Ruby gibi dinamik diller için C / C ++ ile benzer ve karşılaştırılabilir performansa sahip derleyiciler oluşturabilir misiniz?

Bence cevap "evet" . Ayrıca mevcut C / C ++ mimarisini verimlilik açısından bile aşabileceklerine inanıyorum (biraz da olsa).

Sebep basit: Çalışma zamanında derleme zamanından daha fazla bilgi var.

Dinamik tipler sadece ufak bir engeldir: Bir fonksiyon her zaman veya neredeyse her zaman aynı argüman tipleri ile yürütülürse, bir JIT optimizatörü bu özel durum için bir şube ve makine kodu oluşturabilir. Ve yapılabilecek çok şey var.

Bkz Dinamik Diller Strike Geri , Google'ın Steve Yegge tarafından bir konuşma (sanırım bir yerlerde, bir video sürümü de vardır). V8'den bazı somut JIT optimizasyon teknikleri kullanıyor. İlham verici!

Önümüzdeki 5 yıl içinde sahip olacağımız şeyi dört gözle bekliyorum!


2
İyimserliği seviyorum.
Dave Clarke

Steve'in konuşmasında bazı çok özel yanlışlık eleştirileri olduğuna inanıyorum. Onları bulduğumda göndereceğim.
Konrad Rudolph

1
@DaveClarke beni koşmaya devam ettiren şey :)
Kos

2

Görünüşe göre bunun teorik olarak mümkün olduğunu ya da uzak bir gelecekte olduğunu düşünen insanlar bence tamamen yanlış. Mesele, dinamik dillerin tamamen farklı bir programlama stili sağlaması ve getirmesi gerçeğinde yatmaktadır. Aslında, her iki özellik birbiriyle bağlantılı olsa bile, fark iki yönlüdür:

  • Semboller (değişkenler veya daha doğrusu id <-> her türlü veri bağları) yazılmaz.
  • Yapılar (veriler, çalışma zamanında yaşayanların tümü), öğelerinin türleri tarafından da türetilmez.

İkinci nokta ücretsiz jeneriklik sağlar. Buradaki yapıların kompozit öğeler, koleksiyonlar, aynı zamanda kendileri ve hatta her türlü (hatta) rutinleri (fonksiyonlar, eylemler, işlemler) olduğuna dikkat edin ... Yapıları element türlerine göre yazabiliriz, ancak ilk noktadan dolayı Yine de çalışma zamanında kontrol olur. Sembolleri yazmış olabiliriz ve yine de eleman tiplerine göre yazılmamış olanları da yapılandırdık (bir dizi asadece bir ints dizisi olarak değil bir dizi olarak yazılır), ancak bu birkaç kişi bile dinamik bir dilde doğru olmayabilir ( aaynı zamanda dizi).

L

  • ElementLL
  • Tüm semboller bu tiptedir Element, herhangi bir elementleri tutabilirlerL
  • tüm yapılar (yine model rutinleri dahil) yalnızca Elemanın

Bana göre bu sadece büyük bir perf ceza olduğu açıktır; ve diğer sonuçlarda iyi tanımlanmış olan tüm sonuçlara bile dokunmuyorum (programın duyarlılığını sağlamak için gerekli her türlü çalışma zamanı sayısızını kontrol ediyor).


+1 Çok ilginç. Cevabımı okudun mu? Cevabınız daha fazla ayrıntı ve ilginç bir bakış açısı sunsa da, siz ve benim düşüncem birbirine benziyor.
Patrick87

Dinamik dillerin yazılmaması gerekmez. Dinamik bir dilin modelini C'ye uygulamak, optimizasyon olanaklarını ciddi şekilde kısıtlar; derleyicinin üst düzey optimizasyonları (örneğin, değişmez veriler) tanımasını çok zorlaştırır ve bazı temel işlemleri (örn. işlev çağrıları) C'ye gitmeye zorlar. preevaluated; Yerel derleyiciler önemli ölçüde daha iyi performans gösterme eğilimindedir, bayt kodu kod çözme arasındaki farkı doğrulayabileceğinden şüpheliyim.
Gilles,

@ Patrick87: haklısın, düşünce çizgilerimiz çok benzer görünüyor (daha önce okumamıştım, üzgünüm, yansıma benim şu an C de dyn lang uygulamaktan geliyor).
Spir

@Gilles: Eğer statik olarak yazılmamışsa, "... yazılmaya gerek yok" konusunda hemfikirim . Fakat insanların genel olarak dyn pençeleri hakkında düşündükleri bu değil sanırım. Ben şahsen jenerikliği (yukarıdaki cevapta verilen genel anlamda) onsuz yaşamak için çok daha güçlü ve çok daha zor bir özellik olarak görüyorum. Verilen (görünüşte polimorfik) bir türün nasıl tanımlanabileceği konusundaki düşüncemizi genişleterek veya doğrudan örneklere daha fazla esneklik vererek, statik türlerle başa çıkmanın yollarını kolayca bulabiliriz.
Spir

1

Tüm cevapları detaylı olarak okuyacak vaktim olmadı ... ama çok eğlendim.

Altmışlarda ve yetmişli yılların başlarında benzer bir tartışma yaşandı (bilgisayar bilimleri tarihi sıklıkla kendini tekrarlar): bir programcı tarafından manuel olarak üretilen derleme kodu, makine kodu kadar verimli kod üretmek için derlenebilir. Herkes bir programcının herhangi bir programdan daha akıllı olduğunu bilir ve çok akıllı bir optimizasyon ile ortaya çıkabilir (aslında çoğunlukla şimdi peephole optimizasyonu olarak adlandırılan şeyi düşünerek). Bu elbette ki benim açımdan ironi.

Hatta bir kod genişletme kavramı vardı: bir derleyici tarafından üretilen kodun boyutunun, iyi bir programcı tarafından üretilen aynı program için kod boyutuna oranı (sanki bunlardan çok fazla olmuş gibi). Tabii ki fikir bu oranın her zaman 1'den büyük olduğuydu. Zamanın dilleri aydınlar için Cobol ve Fortran 4 ya da Algol 60 idi. Lisp'in düşünülmediğine inanıyorum.

Pekala, birisinin derleyici kodunu bazen genişleme oranını 1 alabilen bir derleyici ürettiğine dair bazı söylentiler vardı. İnsanlar o zamanlar kod büyüklüğü hakkında endişeliydiler (küçük anılar), fakat aynı şey hız ya da enerji tüketimi için de geçerli. Sebeplere girmeyeceğim.

Tuhaf özellikler, bir dilin dinamik özellikleri önemli değil. Önemli olan, nasıl kullanıldıkları, kullanılıp kullanılmadıkları. Performans, hangi birimdeki (kod boyutu, hız, enerji, ...) genellikle programların çok küçük bölümlerine bağlıdır. Dolayısıyla, etkileyici güç veren tesislerin gerçekten engel olamayacakları için iyi bir şans var. İyi programlama pratiği ile, gelişmiş tesisler yeni yapıları (lisp dersi) hayal etmek için sadece disiplinli bir şekilde kullanılır.

Bir dilin statik olarak yazılmaması, bu dilde yazılmış programların statik olarak yazılmadığı anlamına gelmez. Öte yandan, bir programın kullandığı tip sisteminin, bir tip denetleyicisinin şu anda var olması için henüz yeterince resmileştirilmemiş olması olabilir.

Tartışmada, en kötü durum analizine ("problemi durdurma", PERL ayrıştırma) birkaç referans var. Ancak en kötü durum analizi çoğunlukla alakasızdır. Önemli olan, tanımlanmış veya anlaşılmış veya deneyimli, ancak çoğu durumda veya faydalı durumlarda olan şeydir. İşte doğrudan program optimizasyonu ile ilgili başka bir hikaye geliyor. Uzun zaman önce Teksas'taki büyük bir üniversitede doktora öğrencisi ve danışmanı arasında (daha sonra ulusal akademilerden birinde seçildi) gerçekleşti. Hatırladığım kadarıyla, öğrenci danışmanın takip edilemez olduğunu gösterdiği bir analiz / optimizasyon problemi üzerinde çalışmakta ısrarcıydı. Yakında onlar artık konuşma açısından değildi. Ancak öğrenci haklıydı: çoğu pratik durumda sorun yeterince takip edilebiliyordu; bu nedenle ürettiği tezin referans çalışması haline geldi.

Ve Perl parsing is not computablebu cümle ile ne kastedilse, ML ile benzer bir problemin olduğu ve oldukça iyi bir şekilde biçimlendirilmiş bir dil olduğu ifadesiyle ilgili daha fazla yorum yapmak için . Type checking complexity in ML is a double exponential in the lenght of the program.Bu, çok da önemli ve resmi bir sonuçtur ve en önemsiz durum karmaşıklığıdır ... hiç önemli değil. Afaik, ML kullanıcıları hala tip kontrolcüyü patlatacak pratik bir program bekliyor.

Daha önce olduğu gibi birçok durumda, insan zamanı ve yetkinliği bilgisayar gücünden daha azdır.

Geleceğin asıl sorunu, hala kullanılan tüm eski yazılımı yeniden yazmak zorunda kalmadan, yeni bilgileri, yeni programlama formlarını bütünleştirmek için dillerimizi geliştirmek olacaktır.

Matematiğe bakarsanız, bu çok büyük bir bilgi birikimidir. Onu ifade etmek için kullanılan diller, notasyonlar ve kavramlar yüzyıllar içinde gelişmiştir. Eski teoremleri yeni konseptlerle yazmak kolaydır. Ana kanıtları uyarlıyoruz, ancak pek çok sonuç için canınızı sıkmıyoruz.

Ancak programlama durumunda, tüm ispatları sıfırdan yeniden yazmak zorunda kalabiliriz (programlar ispattır). Gerçekte ihtiyacımız olan şey çok yüksek seviyede ve geliştirilebilir programlama dilleri olabilir. Doktoru tasarımcıları takip etmekten mutluluk duyacaktır.


0

Birkaç not:

  • Tüm yüksek seviye dilleri dinamik değildir. Haskell çok yüksek seviyede, ancak tamamen statik yazıyor. Rust, Nim ve D gibi programlama dilleri bile olsa sistemler, üst düzey soyutlamaları özlü ve verimli bir şekilde ifade edebilir. Aslında, dinamik diller kadar özlü olabilirler.

  • Dinamik diller için son derece optomizing zamanından önce derleyiciler var. İyi Lisp uygulamaları eşdeğer C'nin yarısına ulaşır.

  • JIT derlemesi burada büyük bir kazanç olabilir . CloudFlare'nın Web Uygulaması Güvenlik Duvarı, LuaJIT tarafından yürütülen Lua kodunu oluşturur. LuaJIT, gerçekte alınan yürütme yollarını (tipik olarak saldırı dışı yollar) yoğun şekilde optimize eder; sonuç olarak, kod, gerçek iş yükünde statik bir derleyici tarafından üretilen koddan çok daha hızlı çalışır. Profil güdümlü optimizasyona sahip statik bir derleyiciden farklı olarak, LuaJIT çalışma zamanında yürütme yollarındaki değişikliklere uyum sağlar.

  • Deoptimizasyon da çok önemlidir. Maymun biçimli bir sınıfın kontrol edilmesi gereken JIT-derlenmiş kodun yerine, maymun yakalama eylemi, çalışma zamanında sistemde eski tanımlamaya bağlı olan makine kodunu kaldıran bir kanca tetikler.


Bu nasıl bir cevap? Belki de referanslar eklerseniz, üçüncü kurşun olabilir.
Raphael

Ben çok PGO tipik iş yükü altında web uygulama kodu için LuaJIT performansını ulaşamasa iddianın şüpheci.
Konrad Rudolph

@KonradRudolph Bir JIT’in temel avantajı, JIT’in kodu farklı yollar ısınırken uyarlamasıdır.
Demi

@Demetri Bunu biliyorum. Ancak bunun bir avantaj olup olmadığını ölçmek çok zor - cevabımı ve oradaki yorum tartışmasını görün. Özetle: JIT kullanımdaki değişime uyum sağlayabilse de, çalışma süresinde bir ek yüke neden olan işleri izlemesi gerekir. Bunun için ayrılma bile sezgisel olarak yalnızca davranışta sık değişikliklerin meydana geldiği yerdir. Web uygulamaları için, muhtemelen optimizasyonun fayda sağladığı tek (veya çok az) bir kullanım modeli vardır, bu nedenle uyarlanabilirlikten kaynaklanan minimum performans artışı, sürekli profillemenin yükünü dengelemez.
Konrad Rudolph
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.