2010-06-16 16 views
7

Bu gibi görünen kod (gösterilen tüm kullanımlar gösteriliyor):Derleyici, bir iç döngüden kaçmayı optimize eder mi?

bool done = false; 
for(int i = 0; i < big; i++) 
{ 
    ... 
    for(int j = 0; j < wow; j++) 
    { 
    ... 
    if(foo(i,j)) 
    { 
     done = true; 
     break; 
    } 
    ... 
    } 
    if(done) break; 
    ... 
} 

herhangi bir derleyici bunu dönüştürür:

for(int i = 0; i < big; i++) 
{ 
    ... 
    for(int j = 0; j < wow; j++) 
    { 
    ... 
    if(foo(i,j)) 
     goto __done; // same as a labeled break if we had it 
    ... 
    } 
    ... 
} 
__done:; 

Not:if(done)break; atlanır ve ölü kod olarak kaldırılır, ayrıca done'ün tamamen kaldırılmasıyla da ilgilenirim.

+3

, böyle iki alt çizgi ile başlar tüm simgeleri tanımlamak gerekir; Bu semboller saklıdır. –

+8

Sembol, bir optimizasyon geçişinin sonucudur, e.i. derleyici tarafından oluşturulur. Bu ismi kullandım * çünkü * rezerve edilmiş/dahili bir isim gösteriyor. – BCS

+0

Ve soru: neden bu bir işlevde sıkışmış değil?Bir 'return' sonra kullanabilirsiniz;) –

cevap

14

Açıkçası bu derleyici bağlıdır. Emin olmadığınız zaman yapılacak en iyi şey, derleyicinin derleme çıktısını görüntülemektir (tüm popüler derleyicilerin bunun için bir anahtarı vardır). Derlemeyi bilmiyor olsanız bile, en azından hata ayıklama sürümünü en iyileştirilmiş sürümle karşılaştırabilirsiniz.

söyleniyor, bu goto kötü bir fikir değil az olduğu durumlardan biridir. İç döngüden kurtulmak için onu kullanmaktan çekinmeyin.

Düzenleme

Sadece VS2010 aşağıdaki çalıştı ve gerçekten dış koşullu optimize kapsamaz:

bool done = false; 
for(int i = 0; i < 10; i++) 
{ 
    for(int j = 0; j < 10; j++) 
    { 
     if(i == 7 && j == 3) 
     { 
      done = true; 
      break; 
     } 
    } 
    if(done) break; 
} 
return 0; 
+16

+1 okumak için ilginç olmuştur. Şimdiye kadar çok fazla kişi, gotoların, kırılmaların, fonksiyonlardan çok sayıda geri dönüş noktasının ve diğer benzer şeylerin, kodun anlaşılması zor olduğunda kötü olduğu gerçeğini görmezden geldiler. Böyle şeylerin doğru kullanımı, gayet iyi. – paxdiablo

+1

Kimsenin özlemediğinden emin olmak için kalın :) – Cogwheel

+0

Yah, orada bir hakem var. OTOH etiketli bir mola daha iyi ve eğer bir kod incelemesinde onu savunmak zorunda kalmamı engelliyorsa, derleyici ile benim için bir sihir yapıyor olacağım. – BCS

7

GNU derleyici sadece, optimizasyon seviyesine -O1 ile başlayan (kullanıyorum gcc yapar x86_64'lerde 4.5.1) .L14 Eğer __done yerleştirilen tam yerleştirilen etikettir

call _Z3fooii // al = foo(i,j) 
testb %al, %al 
jne .L14 
... 

:

Daha iyi bir soru olabilir: Bu optimizasyonu yapmaz Modern hangi derleyici?

+1

SNC - en azından sahip olduğumuz versiyon değil. – Crashworks

1

Birlikte GCC 4.2.1 denedim aşağıdaki: Bu dan ***

33: e8 fc ff ff ff   call 34 <bar()+0x34> ; call to foo* 
    38: 84 c0     test %al,%al 
    3a: 74 e5     je  21 <bar()+0x21> ; next loop iteration 
    3c: 83 c4 10    add $0x10,%esp 
    3f: 5b      pop %ebx 
    40: 5e      pop %esi 
    41: 5d      pop %ebp 
    42: c3      ret 

:

// Prevent optimizing out calls to foo and loop unrolling: 
extern int big, wow; 
bool foo(int,int); 

void 
bar() 
{ 
    int done = false; 
    for(int i = 0; i < big; i++) 
    { 
     for(int j = 0; j < wow; j++) 
     { 
      if(foo(i,j)) 
      { 
       done = true; 
       break; 
      } 
     } 
     if(done) 
      break; 
    } 
} 

... ve -O3 ile postamble düz aracılığıyla düşer Bağlantısız nesne dosyası, call 34 aslında foo'a çağrı yapıyor.

+1

yani '3a' doğrudan 42’deki son noktaya mı gidiyor? – BCS

+0

@BCS, 0x3a, AL sıfır olduğunda döngü başlangıcına kadar dalları (foo false döndürdü), sadece postamble devam eder (kaydeder kaydeder, önceki yığın çerçevesini geri yükler) 3c, 3f, .. –

4

Ben fark eder ... snarky olmaya çalışıyorum, ama değilim? Genel olarak, derleyiciler işlerine izin vermenin en iyi yol olduğunu düşünüyorum ve bu iş "en iyi" yi üretmektir ("en iyi" nin ihtiyaçlarınıza bağlı olarak değişebileceğine dikkat edin). Kaynak kodunuzu verilen derlenmiş kod. Kodunuzdaki herhangi bir performans değerlendirmesi bir profiler ve algoritmik karmaşıklık hakkında iyi bir çalışma bilgisi ile tanımlanmalıdır. Eğer sadece meraklı iseniz

, o zaman bu yorumunu dikkate almayın. Ama niyetiniz bir şekilde kodunuzu optimize etmekse, o zaman çok daha iyi yollar olduğunu düşünüyorum. Bu arada

+1

ret kadar derleyiciler bu işi çok iyi yapmazlar - en azından yaptıkları gibi değil. – Crashworks

+0

@Crashworks, belirli bir derleyiciye mikro optimizasyon ile ilgili problem, sadece derleyiciye özgüdür. Bazı yeni optimizasyonlar yapmasını aktif olarak engellerseniz, kodunuz söz konusu derleyicinin sonraki sürümlerinde önemli ölçüde gerileyebilir. Derleyicinin dil kısıtlamaları (aşırı nesne kopyalama, takma ad, vb.) Nedeniyle optimize edemediğini bildiğiniz yerlerde en iyi duruma getirmek daha iyidir. Bu tanjantta, derleyicinin eksik olduğu ve dil özelliklerinin buna izin vermediği için hangi optimizasyonların yapılmadığını bilmek zordur. –

+2

Biraz katılıyorum Crash, ama hala temel olarak önemli olan şeyin algoritmik karmaşıklığı anlamak olduğunu düşünüyorum. Dünyadaki en iyi derleyici, bazı shoddy doğrusal arama veya kötü dize birleştirme kodunu düzeltebilir. Derleyicileri kara kutu olarak düşünmek için daha üretken buluyorum çünkü bizi en çok kontrol ettiğimiz şeylerin sorumluluğunu almamıza zorlar: Kendi kodumuz. – kidjan

İlgili konular