Neden hız için soyutlama yapmak zorundayız?


11

Yüksek seviyeli diller neden görünüşte daha düşük seviyeli dillere asla ulaşamıyor? Üst düzey dillere örnek olarak Python, Haskell ve Java verilebilir. Düşük seviyeli diller tanımlamak yanıltıcıdır olurdu, ama hadi C. Karşılaştırmalar İnternet çevresindeki tüm bulunabilir söylemek ve hepsi C bazen 10 veya daha fazla kat, çok daha hızlı olduğu konusunda hemfikirdir.1

Performansta bu kadar büyük bir fark yaratan şey nedir ve üst düzey diller neden yetişemiyor?

Başlangıçta bunun tüm derleyicilerin hatası olduğuna ve gelecekte her şeyin düzeleceğine inandım, ancak en popüler üst düzey dillerden bazıları on yıllardır var ve hız söz konusu olduğunda hala geride kalıyorlar. C sözdizimi ağacına benzer bir şekilde derleyip makine kodunu oluşturan prosedürleri takip edemezler mi? Ya da belki de sözdiziminin kendisiyle ilgili bir şey mi?


1 Örnekler:


5
"ve hepsi C'nin çok daha hızlı olduğu konusunda hemfikir" - bu kesinlikle yanlış.
Raphael

2
Her neyse, yazının en iyi benzer şekilde kötü düşünülmüş bir soruya verdiğim cevapla yanıtlandığını düşünüyorum ; çiftleme?
Raphael

2
Buraya ve buraya da bakınız . Önemsiz cevaplara dikkat edin.
Raphael

İlgili: stackoverflow.com/questions/6964392/… Tüm "üst düzey diller" mitinin yavaş olması oldukça üzücü.
xji

Soyutlama ile başkalarına katılıyorum! = Yavaşlık, ama korkarım ki bilgisayar bilimi öğretmenlerinin (ben olduğum) farkında olmadığı çok daha büyük bir sorun var. Gerçek programlar (1000 satır ve üstü) için bunları yapmanın birçok yolu vardır ve bunlar performans açısından büyüklük sıralarına göre farklılık gösterebilir. Sadece big-O'yu düşünmek bu noktayı tamamen özlüyor. Buradan kontrol edin .
Mike Dunlavey

Yanıtlar:


19

Bazı efsaneleri tartışmak

  1. Hızlı bir dil diye bir şey yoktur. Bir dil genellikle hızlı kod üretebilir, ancak farklı diller farklı ölçütlerde mükemmelleşir. Dilleri belirli bir dizi kusurlu ölçütte sıralayabiliriz, ancak dilleri boşlukta sıralayamayız.

  2. C kodu daha hızlı olma eğilimindedir, çünkü her santimetrede performansa ihtiyaç duyan insanlar C kullanır. hız hakkında ve optimum Python kodu yazmadı. Bunu özellikle Haskell gibi dillerde görüyoruz. Gerçekten çok denerseniz , C ile eşit performans gösteren Haskell yazabilirsiniz. Ancak çoğu insanın bu performansa ihtiyacı yoktur, bu yüzden bir sürü kusurlu karşılaştırmamız var.

  3. Bazen, C'yi hızlandıran soyutlama değil, güvenlik değildir. Dizi sınırları ve boş işaretçi kontrollerinin olmaması zamandan tasarruf sağlar ve yıllar boyunca çok sayıda güvenlik açığının sebebi olmuştur.

  4. Diller hızlı değil, uygulamalar hızlı. Birçok soyut dil yavaş başlar, çünkü hız hedef değildir, ancak daha fazla optimizasyon eklendikçe hızlanır.

Hız dengesizliğine karşı soyutlama belki de yanlıştır. Daha iyi bir karşılaştırma öneririm:

Basitlik, hız, soyutlama: İki tane seçin.

Farklı dillerde özdeş algoritmalar çalıştırıyorsak, hız sorunu "Bu işi yapmak için çalışma zamanında ne kadar şey yapmamız gerekiyor?"

Python veya JavaScript gibi oldukça basit bir dilde , verilerin çalışma zamanına kadar temsilini bilmediğimizden, çalışma zamanında çok sayıda işaretçi referansı ve dinamik kontroller oluyor ve bunlar yavaş.

Aynı şekilde, bilgisayarınızı batırmamanız için yapılması gereken birçok kontrol vardır. Python'da bir işlevi çağırdığınızda, aradığınız nesnenin gerçekte bir işlev olduğundan emin olmanız gerekir, aksi takdirde korkunç şeyler yapan rasgele kod yürütebilirsiniz.

Son olarak, çoğu soyut dilde çöp toplama yükü vardır. Çoğu programcı, dinamik olarak tahsis edilen belleğin yaşamlarını izlemek zorunda kalmanın bir acı olduğunu ve bir çöp toplayıcının çalışma zamanında bunu yapmasını tercih etti. Bu, bir C programının GC için harcama yapması gerekmediği zaman alır.

Özet Yavaş demek değil

Ancak, hem soyut hem de hızlı diller vardır. Bu çağda en baskın olan Rust'tur. Bir ödünç denetleyici ve sofistike bir tip sistemi sunarak soyut koda izin verir ve çalışma zamanında yapmamız gereken iş miktarını (yani çöp toplama) azaltmak için derleme zamanı bilgilerini kullanır.

Statik olarak yazılan herhangi bir dil, çalışma zamanı denetimi sayısını azaltarak bize zaman kazandırır ve derleme zamanında bir daktiloyu memnun etmemizi talep ederek karmaşıklık getirir. Benzer şekilde, bir değerin tür sistemine boş olup olamayacağını kodlayan bir dilimiz varsa, derleme zamanı boş gösterici denetimleriyle zaman kazanabiliriz.


2
"C kodu daha hızlı olma eğilimindedir çünkü performansın her santimine ihtiyaç duyan insanlar C" kullanırlar. "Y yıllık deneyimi Z olan X yıllık öğrenciler / profesyoneller tarafından yazılan kodun ortalama çalışma süresi" formunun karşılaştırmasını görmek istiyorum. C'nin cevabının genellikle küçük X ve Y için "kod doğru değil" olmasını bekliyorum . Performans C vaatleri potansiyelinden yararlanmak için ne kadar daha fazla deneyim / uzmanlığa ihtiyacınız olduğunu görmek gerçekten ilginç olurdu .
Raphael

Haskell gerçekten kuralı ispatlayan bir istisnadır. ;) Sanırım C ++, paylaşılan işaretçileri yuvalamadığınız ve C kadar hızlı olacağı sürece akıllı işaretçileriyle GC hakkında oldukça makul bir orta yol buldu.
Kaveh

0

İşte bununla ilgili birkaç temel fikir.

  • wrt soyutlama vs hız yapmak için kolay bir karşılaştırma / vaka çalışması java vs c ++. java, c ++ 'ın bellek yönetimi gibi alt düzey yönlerini soyutlamak için tasarlanmıştır. ilk günlerde (1990'ların ortalarında dilin icadı etrafında), java çöp tespiti çok hızlı değildi, ancak birkaç on yıl süren araştırmadan sonra, çöp toplayıcıları son derece ince / hızlı / optimize edildi, bu nedenle çöp toplayıcıları büyük ölçüde ortadan kaldırıldı. Java'da performans tahliyesi. Örneğin, bu 1998 başlığına bile bakın: Performans testleri Java'yı C ++ / javaworld kadar hızlı gösterir

  • programlama dilleri ve onların uzun evrimi, bir çeşit transandant tasarım modeli olarak doğal bir "piramidal / hiyerarşik yapıya" sahiptir. piramidin tepesinde piramidin diğer alt bölümlerini kontrol eden bir şey vardır. diğer bir deyişle, yapı taşları yapı taşlarından yapılır. bu API yapısında da görülebilir. bu anlamda, daha büyük soyutlama her zaman piramidin üstünde diğer bileşenleri kontrol eden bazı yeni bileşenlere yol açar. bu yüzden bir anlamda o kadar çok değil ki tüm diller birbirleriyle aynı seviyededir, ancak bu diller diğer dillerdeki rutinleri gerektirir. Örneğin, çok sayıda komut dosyası dili (python / ruby) genellikle C veya C ++ kitaplıklarını çağırır; sayısal veya matris yordamları bunun tipik bir örneğidir. dolayısıyla daha yüksek seviye ve daha düşük seviyeli diller vardır ve yüksek seviyeli diller daha düşük seviyeli diller olarak adlandırılır. bu anlamda bağıl hızın ölçülmesi gerçekten karşılaştırılamaz.

  • soyutlama / hız dengesini, yani temel tasarım hedefini optimize etmek için her zaman yeni diller icat edildiğini söyleyebiliriz. belki o kadar çok değil, daha büyük soyutlama her zaman hızı feda eder, ancak yeni tasarımlarla her zaman daha iyi bir denge aranır. Örneğin, Google Go, aynı anda hem üst düzey hem de performansta olmak için özel olarak satışa yönelik olarak optimize edilmiştir. bkz. Google Go: Google'ın programlama dili neden işletme / teknoloji dünyasında Java ile rekabet edebilir?


0

Performans hakkında düşünmeyi sevdiğim yol, "kauçuğun yolla buluştuğu yer". Bilgisayar, soyutlamaları değil talimatları uygular.

Ne görmek istiyorum: yürütülen her talimat sonuç sonucuna önemli ölçüde katkıda bulunarak "tutmak" kazanıyor? Çok basit bir örnek olarak, 1024 girişlik bir tabloda bir giriş aramayı düşünün. Bu 10 bitlik bir sorundur çünkü program cevabı bilmeden önce 10 biti "öğrenmek" zorundadır. Algoritma ikili arama ise, her yineleme 1 bit bilgiye katkıda bulunur, çünkü belirsizliği 2 kat küçültür. Yani her bit için bir tane olmak üzere 10 yineleme gerekir.

Öte yandan, doğrusal arama başlangıçta çok verimsizdir, çünkü ilk iterasyonlar belirsizliği çok küçük bir faktörle azaltır. Yani harcanan çaba için fazla bir şey öğrenmiyorlar.

Tamam, bu yüzden derleyici kullanıcının iyi talimatları "soyut" olarak kabul edilen bir şekilde sarmasına izin verebilirse, sorun değil.


0

Doğası gereği soyutlama, hem programcıya hem de sistemin alt katmanlarına (derleyici, kütüphaneler ve çalışma zamanı sistemi) bilgi iletişimini azaltır. Soyutlama lehine, bu genellikle alt katmanların programlayıcının belirtilmemiş herhangi bir davranışla ilgisi olmadığını varsayarak, belirtilen davranışı sağlamada daha fazla esneklik sağlar .

Bu "umrumda değil" özelliğinden potansiyel bir fayda örneği veri düzenindedir. C'de (düşük soyutlama), derleyici veri düzeni optimizasyonlarında daha kısıtlıdır. Derleyici, sıcak / soğuk veya yanlış paylaşım-kaçınma optimizasyonlarının yararlı olacağını fark edebilseydi (örneğin, profil bilgileri aracılığıyla), genellikle böyle bir uygulamanın uygulanması önlenir. ("Sanki" belirtme özgürlüğü vardır, yani spesifikasyona daha soyut davranmak, ancak tüm potansiyel yan etkileri elde etmek derleyiciye bir yük getirir.)

Daha soyut bir spesifikasyon, takas ve kullanımlardaki değişikliklere karşı daha sağlamdır. Alt katmanlar, yeni sistem özellikleri veya yeni kullanımlar için programı yeniden optimize etmede daha az kısıtlıdır. Daha somut bir şartname ya bir programcı tarafından yeniden yazılmalı ya da "sanki" davranışı garanti etmek için alt katmanlar tarafından ek çaba gösterilmelidir.

Soyutlamayı gizleyen bilginin performansı engelleyen yönü, alt katmanların tipik olarak "bilmiyorum" olarak işleyeceği "ifade edemez" dir. Bu, alt katmanların optimizasyon için yararlı bilgileri tipik genel kullanım, hedefli kullanım veya belirli profil bilgileri gibi diğer araçlardan ayırt etmesi gerektiği anlamına gelir.

Bilgi gizlemenin etkisi diğer yönde de çalışır. Programcı, her ayrıntıyı dikkate almak ve belirtmek zorunda kalmadan daha üretken olabilir, ancak programcı daha üst düzey tasarım seçimlerinin etkisi hakkında daha az bilgiye sahip olabilir.

Öte yandan, kod daha spesifik olduğunda (daha az soyut), sistemin alt katmanları söylendiklerini yapmaları daha basit bir şekilde yapabilir. Kod, hedeflenen kullanımı için iyi yazılmışsa, hedeflenen kullanımına iyi uyacaktır. Daha az soyut bir dil (veya programlama paradigması) , programlayıcının uygulamayı detaylı tasarım ve belirli bir dilde alt katmanlara kolayca iletilmeyen bilgileri kullanarak optimize etmesini sağlar .

Daha önce belirtildiği gibi, ek programcı beceri ve çabası değerli sonuçlar üretebildiğinde daha az soyut dil (veya programlama teknikleri) caziptir. Daha fazla programcı çabası ve becerisi uygulandığında, sonuçlar genellikle daha iyi olacaktır. Buna ek olarak, performans açısından kritik uygulamalar için daha az kullanılan bir dil sistemi (bunun yerine geliştirme çabası veya güvenilirliği vurgulamak - sınır kontrolleri ve çöp toplama sadece programcı üretkenliği değil, doğrulukla ilgilidir, soyutlamanın programcı üzerindeki zihinsel yükü azaltması güvenilirliği artırabilir) performansı artırmak için daha az baskı olacaktır.

Özgüllük, kendinizi tekrar etmeme ilkesine karşı da çalışır, çünkü optimizasyon genellikle kodu belirli bir kullanıma uyarlayarak mümkündür. Bunun bariz güvenilirlik ve programlama çabası sonuçları vardır.

Bir dil tarafından sağlanan soyutlamalar, daha az ağır bir soyutlama seçmenin hiçbir yolu olmayan, istenmeyen veya gereksiz çalışmaları da içerebilir. Gereksiz çalışmalar bazen alt katmanlar tarafından keşfedilip çıkarılabilirken (örneğin, sınır kontrolleri bir döngü gövdesinden çıkarılabilir ve bazı durumlarda tamamen kaldırılabilir), bunun geçerli bir optimizasyon olduğunu belirlemek, daha fazla "beceri ve çaba" gerektiriyor derleyici.

Dil yaşı ve popülerliği, hem yetenekli programcıların mevcudiyetinde hem de sistemin alt katmanlarının kalitesinde (olgun kütüphaneler ve kod örnekleri dahil) dikkate değer faktörlerdir.

Bu tür karşılaştırmalardaki bir başka çelişkili faktör, vaktinden önce derleme ile tam vaktinde derleme arasındaki biraz dik farktır. Tam zamanında derleme, profil bilgilerini (profil çalıştırmaları sağlamak için programcıya güvenmemek) ve sisteme özgü optimizasyonu (zamanından önce derleme daha geniş uyumluluğu hedefleyebilir) daha kolay bir şekilde kullanabilirken, agresif optimizasyonun ek yükü şu şekilde hesaplanır: çalışma zamanı performansının bir parçası. JIT sonuçları önbelleğe alınabilir, bu da yaygın olarak kullanılan kod için ek yükü azaltır. (İkili yeniden optimizasyon alternatifi, JIT derlemesinin bazı avantajlarını sağlayabilir, ancak geleneksel ikili dağıtım biçimleri, kaynak kod bilgilerinin çoğunu, sistemi belirli bir uygulamanın amacını fark etmeye teşebbüs etmeye zorlayabilir.)

(Daha düşük soyutlama dilleri, programcı kontrolüne vurgu yaptıkları için, önceden derleme kullanımını tercih eder. Yükleme zamanı derlemesi tolere edilebilir, ancak bağlantı zamanı uygulama seçimi daha fazla programcı kontrolü sağlar. JIT derlemesi önemli kontrolü feda eder. )

Kıyaslama metodolojisi de var. Eşit çaba / beceri oluşturmak etkili bir şekilde imkansızdır, ancak bu şekilde bile gerçekleştirilebilirse, dil hedefleri sonuçları önyargılar. Düşük bir maksimum programlama süresi gerekiyorsa, daha az soyut bir dil için bir program, daha soyut bir dilde basit bir deyimsel ifadeye kıyasla tamamen yazılmayabilir. Yüksek bir maksimum programlama süresi / çabasına izin verilirse, daha düşük soyutlama dillerinin bir avantajı olacaktır. En iyi çaba sonuçları sunan karşılaştırmalar doğal olarak daha az soyut diller lehine taraflı olacaktır.

Diğer programlama paradigmalarının avantajlarını elde etmek için bazen bir dilde daha az deyimsel bir şekilde programlamak mümkündür, ancak ifade gücü mevcut olsa bile, bunu yapmak için denemeler uygun olmayabilir.

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.