Bir derleyicinin zaman karmaşıklığı


54

Bir derleyicinin zaman karmaşıklığıyla ilgileniyorum. Açıkçası bu çok karmaşık bir sorudur çünkü birçok derleyici, derleyici seçeneği ve dikkate alınması gereken değişkenler vardır. Özellikle, LLVM ile ilgileniyorum ancak insanların araştırma yapmaya başlayabilecekleri veya yerleri olabileceği düşünceleriyle ilgileneceğim. Oldukça google çok az şey getiriyor.

Benim tahminim üstel, ancak gerçek zaman üzerinde çok az etkisi olan bazı optimizasyon adımları olacağı yönünde olurdu. Örneğin, sayıya göre üstel bir fonksiyonun argümanlarıdır.

Başımın üstünden AST ağacını oluşturmanın doğrusal olacağını söyleyebilirim. IR oluşturma, sürekli büyüyen tablolardaki değerleri ararken ağacın içinde adım atmayı gerektirir, yani veya O ( n log n ) . Kod oluşturma ve bağlama benzer bir işlem türü olacaktır. Bu nedenle, gerçekçi olarak büyümeyen değişkenlerin üstellerini kaldırırsak tahminim O ( n 2 ) olur.O(n2)O(nlogn)O(n2)

Yine de tamamen yanlış olabilirim. Bir fikri olan var mı?


7
Herhangi bir şeyin “üstel”, “doğrusal”, veya O ( n log n ) olduğunu iddia ederken dikkatli olmalısınız . En azından benim için, girişinizi nasıl ölçtüğünüz hiç belli değil (Neye göre üstel? N n için duruyor?)O(n2)O(nlogn)n
Juho

2
LLVM derken, Clang mı demek istiyorsun? LLVM, birkaç farklı derleyici alt projesine sahip büyük bir projedir, bu yüzden biraz belirsizdir.
Nate CK

5
C # için en kötü durum problemleri için en azından üsteldir (NP tam SAT problemini C # ile kodlayabilirsiniz). Bu sadece optimizasyon değil, bir fonksiyonun doğru aşırı yüklenmesini seçmek için de gereklidir. C ++ gibi bir dil için, şablonlar tamamlandığı için karar verilemez.
CodesInChaos

2
@Zane Amacınızı anlamıyorum. Derleme sırasında şablon hazırlığı gerçekleşir. Zor problemleri, doğru bir çıktı üretmek için derleyiciyi bu problemi çözmeye zorlayacak şekilde şablonlara kodlayabilirsiniz. Derleyicinin, turing complete template programlama dilinin bir tercümanı olduğunu düşünebilirsiniz.
KodlarInChaos

3
Birden fazla aşırı yüklemeyi lambda ifadeleriyle birleştirdiğinizde, C # aşırı yük çözünürlüğü oldukça zordur. Bunu bir boolean formülü bu şekilde kodlamak için kullanabilirsiniz, uygulanabilir bir aşırı yüklenme olup olmadığını belirlemek NP-3SAT problemini gerektirir. Sorunu gerçekten derlemek için, derleyici aslında bu formül için çözümü bulmak zorunda, bu daha da zor olabilir. Eric Lippert, blog yazısında Lambda Expressions vs. Anonim Yöntemler, Beşinci Bölüm
CodesInChaos 12:14

Yanıtlar:


50

Sorunuzu yanıtlamak için en iyi kitap muhtemelen şu olabilir: Cooper ve Torczon, "Engineering a Compiler", 2003. Bir üniversite kütüphanesine erişiminiz varsa, bir kopyasını ödünç almanız gerekir.

O(n2)n

O(n)O(n)

O(n)O(1)O(s)s

Ardından, ayrıştırma ağacı tipik olarak bir kontrol akış grafiğine "yassılaştırılır". Kontrol akış grafiğinin düğümleri 3 adresli talimatlar (bir RISC montaj diline benzer) olabilir ve kontrol akış grafiğinin boyutu tipik olarak ayrıştırma ağacının boyutunda doğrusal olacaktır.

O(d)dO(n)n

Daha gelişmiş optimizasyonlar için daha karmaşık analizler yapmak isteyebilirsiniz. Bu noktada travmalara çarpmaya başlarsınız. Analiz algoritmalarınızın değerinden çok daha az sürmesini istiyorsunuz.O(n2)tüm programın akış grafiğinin büyüklüğünde bir zamandır, ancak bunun kanıtlanması pahalı olabilecek bilgi olmadan (ve program iyileştirme dönüşümlerini) yapmanız gerekir. Bunun klasik bir örneği, takma ad analizidir; bazı bellek yazıları için, iki yazının aynı bellek yerini asla hedefleyemediğini kanıtlamak istersiniz. (Bir talimatı diğerinin üzerine getirip getiremediğinizi anlamak için bir takma ad analizi yapmak isteyebilirsiniz.) programda (ve böylece kontrol akış grafiğindeki düğüm sayısında üstel.)

Sonra kayıt tahsisine geçersiniz. Kayıt tahsisi, bir grafik renklendirme sorunu olarak ifade edilebilir ve bir grafiğin en az sayıda renkle renklendirilmesinin NP-Hard olduğu bilinmektedir. Bu nedenle çoğu derleyici, makul zaman sınırları içerisinde kayıt dökülme sayısını mümkün olan en iyi şekilde azaltmak amacıyla kayıt dökülmeleriyle birlikte bir çeşit açgözlü buluşsal yöntem kullanmaktadır.

Sonunda kod üretmeye başladın. Kod oluşturma, genellikle, temel bir bloğun , tek girişli ve tek çıkışlı bir dizi doğrusal olarak bağlanmış kontrol akış grafiği düğümü olduğu bir zamanda maksimum bir temel blok yapılır. Bu, ele almaya çalıştığınız grafiğin, temel bloktaki 3-adresli talimatlar grubunun bağımlılık grafiği olduğu ve mevcut makineyi temsil eden bir grafik seti ile kapsamaya çalıştığınız bir problemi kapsayan bir grafik olarak yeniden düzenlenebilir. Talimatlar. Bu problem, en büyük temel bloğun boyutunda (prensipte tüm programın büyüklüğü ile aynı sırada olabilen) büyüktür, bu yüzden bu, tipik olarak, muhtemel kaplamaların sadece küçük bir alt kümesinin olduğu sezgisel tarama ile yapılır. incelemiştir.


4
Thirded! Bu arada, derleyicilerin çözmeye çalıştığı sorunların çoğu (örneğin, kayıt tahsisi) NP zor, ancak diğerleri resmi olarak kararsız. Örneğin, p () bir aramanız ve ardından bir q () aramanız olduğunu varsayalım. Eğer p saf bir işlevse, p () sonsuz döngülemediği sürece çağrıları güvenle yeniden sıralayabilirsiniz. Bunu kanıtlamak durma problemini çözmeyi gerektirir. NP zorlu problemlerde olduğu gibi, bir derleyici yazar mümkün olduğu kadar bir çözüme yaklaşmak için çok az veya çok çaba harcayabilir.
Sahte

4
Oh, bir şey daha: Günümüzde kullanımda teoride oldukça karmaşık olan bazı tip sistemler var. Hindley-Milner tipi çıkarım, DEXPTIME tarafından tamamlanmıştır ve ML benzeri diller onu doğru şekilde uygulamalıdır. Bununla birlikte, çalışma zamanı pratikte doğrusaldır, çünkü a) patolojik durumlar hiçbir zaman gerçek dünya programlarında ortaya çıkmaz ve b) gerçek dünya programcıları, yalnızca daha iyi hata mesajları almak için tip ek açıklamaları koyma eğilimindedir.
Sahte

1
Büyük cevap, eksik görünen tek şey açıklamanın basit kısmıdır, basit bir şekilde dile getirilmiştir: Bir programın derlenmesi O (n) 'de yapılabilir. Herhangi bir modern derleyicinin yapacağı gibi, derlemeden önce bir programı optimize etmek pratik olarak sınırsız bir iştir. Gerçekte geçen süre, işin herhangi bir içsel sınırına göre değil, insanların beklemekten yorulmadan önce derleyicinin bir noktada bitmesi için pratik bir ihtiyaç tarafından yönetilir. Her zaman bir uzlaşmadır.
aaaaaaaaaaaa

@ Sahte, derleyicinin durma problemini (ya da çok kötü NP zor problemlerini) çözmek zorunda kalacağı gerçeği, standartların, derleyicinin belirsiz davranışı olmamasını (sonsuz döngüler ve benzeri gibi) beklemesine izin vermesinin sebeplerinden biridir. ).
von

15

Aslında, bazı diller (C ++, Lisp ve D gibi) derleme zamanında Turing-tamamlanmıştır, bu nedenle derleme genel olarak kararsızdır. C ++ için bu özyinelemeli şablon örneklemesinden kaynaklanıyor. Lisp ve D için, derleme zamanında neredeyse her kodu çalıştırabilirsiniz, böylece derleyiciyi sonsuz bir döngüye atabilirsiniz.


3
Haskell'in (uzantılarıyla birlikte) ve Scala'nın tip sistemleri de Turing-complete'dur, bu da tip kontrolünün sonsuz zaman alabilmesi anlamına gelir. Scala şimdi ayrıca Turing-complete makrolarına da sahip.
Jörg W Mittag

5

C # derleyici konusundaki asıl deneyimimden, bazı programlar için çıktı ikilininin büyüklüğünün girdi kaynağının boyutuna göre katlanarak büyüdüğünü söyleyebilirim (bu aslında C # spec için zorunludur ve azaltılamaz), bu yüzden zaman karmaşıklığı en azından üstel olmalı.

C # 'daki genel aşırı yük çözünürlüğü görevinin NP zor olduğu bilinmektedir (ve gerçek uygulama karmaşıklığı en azından üsteldir).

XML dokümantasyon yorumlarının C # kaynaklarında işlenmesi aynı zamanda derleme zamanında rastgele XPath 1.0 ifadelerinin, üstel, AFAIK'in de değerlendirilmesini gerektirir.


C # ikili dosyalarını bu şekilde havaya uçurtan şey nedir? Bana bir dil böceği gibi geliyor ...
vonbrand 10:14

1
Genel türlerin meta verilerde kodlanma şekli budur. class X<A,B,C,D,E> { class Y : X<Y,Y,Y,Y,Y> { Y.Y.Y.Y.Y.Y.Y.Y.Y y; } }
Vladimir Reshetnikov

-2

Bir dizi açık kaynaklı proje gibi gerçekçi kod tabanlarıyla ölçün. Sonuçları (codeSize, finishTime) olarak çizerseniz, o grafikleri çizebilirsiniz. Verileriniz f (x) = y, O (n) ise, g = f (x) / x çizimleri, veriler genişlemeye başladıktan sonra size düz bir çizgi vermelidir.

Grafik f (x) / x, f (x) / lg (x), f (x) / (x * lg (x)), f (x) / (x * x), vb. sıfıra getirmek, sınırsız artış veya düzleşmek. Bu fikir, boş bir veritabanından başlayarak ekleme zamanlarının ölçülmesi gibi durumlar için kullanışlıdır (yani: uzun bir süre boyunca 'performans sızıntısı' aramak için).


1
Çalışma sürelerinin ampirik ölçümü, hesaplama karmaşıklığı oluşturmaz. Birincisi, hesaplama karmaşıklığı en yaygın olarak en kötü durum çalışma süresi olarak ifade edilir. İkincisi, bir tür ortalama durumu ölçmek isteseniz bile, girdilerinizin bu anlamda "ortalama" olduğunu belirlemeniz gerekir.
David Richerby

Tabii ki sadece bir tahmin. Ancak birçok gerçek veri içeren basit ampirik testler (bir sürü git repo için her taahhüt) dikkatli bir modeli çok iyi geçebilir. Her durumda, bir işlev gerçekten O (n ^ 3) ise ve f (n) / (n n n) 'i çizerseniz, kabaca sıfır eğimli bir gürültülü çizgi elde etmelisiniz. Yalnızca O (n ^ 3) / (n * n) çizdiyseniz, doğrusal olarak yükseldiğini görürsünüz. Aşırı abartırsanız ve çizgiyi hızla sıfıra dalarsanız izlersiniz.
Rob

1
Θ(nlogn)Θ(n2)Θ(nlogn)Θ(n2)

Bir saldırgandan size hizmet vermeme konusunda endişeleniyorsanız, kötü girdi veren, bazı gerçek zamanlı kritik girdi ayrıştırma işlemleri yaptığınız için bilmeniz gereken şeyin bu olduğuna katılıyorum. Derleme zamanlarını ölçen gerçek fonksiyon çok gürültülü olacak ve umursadığımız durum gerçek kod havuzlarında olacak.
Rob

1
Hayır. Soru, sorunun zamanın karmaşıklığını sorar. Bu genellikle, depolardaki kodun çalışma zamanı değil, kesinlikle en kötü çalışma zamanı olarak yorumlanır. Önerdiğiniz testler, derleyicinin belirli bir kod parçasını ne kadar süre kullanmasını beklediğiniz konusunda makul bir yol gösterir; bu, iyi ve kullanışlı bir şeydir. Fakat size problemin hesap karmaşıklığı hakkında neredeyse hiçbir şey söylemediler.
David Richerby
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.