2016-01-10 14 views
5

Powiedziano mi, że pętla while była bardziej wydajna niż pętla for. (c/C++) To wydawało się rozsądne, ale chciałem znaleźć sposób, aby to udowodnić lub obalić.Czy pętle są bardziej wydajne niż pętle?

Próbowałem trzech testów przy użyciu analogicznych fragmentów kodu. Każda zawierająca Nic tylko za lub pętli while z tego samego wyjścia:

  1. czasu kompilacji - mniej więcej takie same
  2. czasu Run - Ta sama
  3. skompilowany kod Intel montażowej i porównano - samą liczbę wierszy i praktycznie ten sam kod:

Czy powinienem spróbować czegoś innego lub czy ktoś może potwierdzić w taki czy inny sposób?

+9

Są takie same.Jedyną różnicą jest logiczna sekwencja operacji i odpowiadająca jej czytelność. – i486

+14

Ktokolwiek ci to powiedział - nie słuchaj już tej osoby. –

+0

Możliwe dup https://stackoverflow.com/questions/3629174/which-loop-is-faster-while-lub-for – oleksii

Odpowiedz

3

Wszystkie pętle według tego samego szablonu:

{ 
// Initialize 
LOOP: 
    if(!(/* Condition */)) { 
     goto END 
    } 

    // Loop body 

    // Loop increment/decrement 
    goto LOOP 
} 
END: 

Nich dwie pętle są takie same:

// A 
for(int i=0; i<10; i++) { 
    // Do stuff 
} 

// B 
int i=0; 
while(i < 10) { 
    // Do stuff 
    i++; 
} 

// Or even 
int i=0; 
while(true) { 
    if(!(i < 10)) { 
     break; 
    } 

    // Do stuff 
    i++; 
} 

Oba są konwertowane na coś podobnego do:

{ 
int i=0; 
LOOP: 
    if(!(i < 10)) { 
     goto END 
    } 

    // Do stuff 

    i++; 
    goto LOOP 
} 
END: 

niewykorzystane/nieosiągalny kod zostanie usunięty z ostatecznego pliku wykonywalnego/biblioteki.

Pętle do-while pomijają pierwsze sprawdzanie warunkowe i są pozostawione jako ćwiczenie dla czytnika. :)

1

Oczywiście LLVM przekształci wszystkie typy pętli w spójną formę (oczywiście w miarę możliwości). Tak długo, jak masz tę samą funkcjonalność, nie ma znaczenia, czy użyjesz for, , do-while lub lub goto do utworzenia pętli, jeśli ma tę samą inicjalizację, warunek zakończenia i instrukcję i ciało aktualizacji, to będzie produkować dokładnie ten sam kod maszynowy.

To nie jest trudne do zrobienia w kompilatorze, jeśli zostało zrobione wystarczająco wcześnie podczas optymalizacji (aby kompilator nadal rozumiał, co faktycznie jest napisane). Celem takiego "utworzenia wszystkich pętli równych" jest to, że potrzebujesz tylko jednego sposobu na zoptymalizowanie pętli, zamiast posiadania jednego dla pętli while, jednego dla pętli for, jednego dla pętli do-while i jednego dla "innych pętli" ".

Nie jest to zagwarantowane dla WSZYSTKICH kompilatorów, ale wiem, że gcc/g ++ będzie również generował prawie identyczny kod, niezależnie od konstrukcji pętli, z której korzystałem, az tego, co widziałem, Microsoft robi to samo.

1

Kompilatory C i C++ faktycznie konwertują kody wysokiego poziomu C lub C++ na kody zespołów, aw zestawie nie mamy pętli while ani for. Możemy tylko sprawdzić stan i przejść do innej lokalizacji.

Tak więc wydajność pętli for lub while zależy w dużym stopniu od tego, jak silna jest optymalizacja kodów przez kompilator.

Jest to dobry papier na optymalizacje kodu:

http://www.linux-kongress.org/2009/slides/compiler_survey_felix_von_leitner.pdf.