Optymalizacja kodu wynikowego
Z Wikipedii
Optymalizacja kodu wynikowego – proces, w którym dosłowna wersja kodu źródłowego, zazwyczaj w postaci jakiegoś drzewa, jest przekształcana w postać umożliwiającą sprawne wykonanie.
Optymalizacja pozwala poprawić wydajność, często jednak taki kod jest trudniejszy do debugowania, ponieważ utracona zostaje pełna odpowiedniość pomiędzy kodem źródłowym a wykonywanym.
Niektóre optymalizacje, jak np. pominięcie wskaźników ramek (ang. omit-frame-pointer), uniemożliwiają działanie debugera na niektórych architekturach. Z drugiej strony pominięcie tych wskaźników zwalnia jeden rejestr procesora czyniąc go dostępnym dla innych celów. Program będzie potrzebował również mniej taktów procesora aby mógł się wykonać, ponieważ ta optymalizacja znosi konieczność zapisywania, ustawiania i przywracania zawartości rejestru przechowującego ten wskaźnik.
Optymalizacja w celu uzyskania wyższej szybkości wykonywania kodu przez procesor może być prowadzona w kilku krokach i na różnych etapach.
[edytuj] Optymalizacje w GCC
Kompilator GCC przeprowadza najpierw optymalizację niezależną od architektury, a następnie (jeśli użytkownik sobie tego zażyczy) optymalizację kodu pod konkretny procesor (lub nawet model procesora).
Optymalizacja ogólna jest wykonywana na zasadach, które są wspólne dla wszystkich maszyn, architektur i procesorów. Możemy sami wybrać odpowiednie opcje, albo wybrać jeden ze zdefiniowanych poziomów optymalizacji (przełączniki -O, -O2 -O3 -Os).
Poszczególne poziomy optymalizacji obejmują:
- -O – podstawowa optymalizacja, jest szybka ale jednocześnie powoduje optymalizację tylko w zakresie podstawowym;
- -O2 – drugi poziom optymalizacji powoduje włączenie wszystkich tych optymalizacji, które nie są niebezpieczne, tzn. nie zostanie włączona żadna optymalizacja, która mogłaby zmienić w istotny sposób działanie programu (np. zmniejszyć precyzję obliczeń zmiennoprzecinkowych);
- -O3 – najwyższy poziom optymalizacji, może powodować problemy w działaniu skomplikowanych programów, zmniejszyć precyzję obliczeń i spowodować znaczny wzrost objętości kodu wykonywalnego programu;
- -Os – nie optymalizuje kodu pod względem prędkości jego wykonania, lecz pod względem rozmiaru pliku wykonywalnego – plik taki będzie wykonywał się wolniej, ale jego rozmiar (szczególnie w porównaniu z -O3) będzie znacząco mniejszy.
Kompilator może również wykonać wiele optymalizacji, aby program lepiej działał na konkretnym procesorze. Jest to związane z pewnymi charakterystycznymi cechami procesora, takimi jak: ilość i rodzaje rejestrów (np. procesory PowerPC mają więcej rejestrów ogólnego przeznaczenia niż Pentium), ilość i algorytmy zarządzające pamięcią cache (aby zmaksymalizować jej użycie). Rodzaje instrukcji (z naciskiem na instrukcje wyspecjalizowane do obróbki pewnych typów danych oraz instrukcje SIMD), wielopotokowość, czy superskalarność mają również ogromne znaczenie z punktu widzenia optymalizacji.
GCC na platformie x86 potrafi optymalizować kod pod szereg różnych procesorów. Włączenie optymalizacji powoduje często, że kod wynikowy nie uruchomi się na innym, podobnym procesorze, lub będzie na nim działał wyjątkowo wolno.