Często podczas pisania kodu, wielokrotnie używam wartości z konkretnego wywołania funkcji. Zdałem sobie sprawę, że oczywistą optymalizacją byłoby uchwycenie tych wielokrotnie używanych wartości w zmiennych. to (pseudo kod):W jaki sposób kompilator może zastosować funkcję eliminacji funkcji nieczytelnych?
function add1(foo){ foo + 1; }
...
do_something(foo(1));
do_something_else(foo(1));
Staje:
function add1(foo){ foo + 1; }
...
bar = foo(1);
do_something(bar);
do_something_else(bar);
Jednak robi to wyraźnie czyni kod mniej czytelny w moim doświadczeniu. Zakładam, że kompilatory nie mogą przeprowadzić tego rodzaju optymalizacji, jeśli nasz wybrany język pozwala funkcjom mieć efekty uboczne.
Ostatnio zajrzałem w to i jeśli dobrze rozumiem, ta optymalizacja jest/może być zrobiona dla języków, w których funkcje muszą być czyste. Nie zaskakuje mnie to, ale podobno można to zrobić także w przypadku nieczystych funkcji. Za pomocą kilku szybkich wyszukiwań Google Znalazłem te fragmenty: GCC 4.7 Fortran improvement
Podczas wykonywania Czołowy optymalizacji opcja -faggressive-funkcja-eliminacja umożliwia usunięcie duplikatu wywołań funkcji nawet dla funkcji nieczystych.
Compiler Optimization (Wikipedia)
Na przykład, w niektórych funkcjach języków nie mogą mieć skutki uboczne. Dlatego jeśli program wykonuje kilka wywołań tej samej funkcji z tymi samymi argumentami, kompilator może od razu wywnioskować, że wynik tej funkcji musi zostać obliczony tylko raz. W językach, w których funkcje mogą mieć efekty uboczne, możliwa jest inna strategia. Optymalizator może określić, która funkcja nie ma skutków ubocznych i ograniczyć takie optymalizacje do funkcji wolnych od skutków ubocznych. Ta optymalizacja jest możliwa tylko wtedy, gdy optymalizator ma dostęp do wywoływanej funkcji.
Z mojego rozumowania oznacza to, że optymalizator może określić, kiedy dana funkcja jest lub nie jest czysta, i wykonać tę optymalizację, gdy funkcja jest. Mówię to, ponieważ jeśli funkcja zawsze wytwarza to samo wyjście, gdy otrzyma to samo wejście i jest wolna od skutków ubocznych, spełni oba warunki, aby zostać uznanym za czysty.
Te dwa fragmenty podnoszą dwa pytania do mnie.
- W jaki sposób kompilator może bezpiecznie wykonać tę optymalizację, jeśli funkcja nie jest czysta? (jak w funkcji eliminacji fagresywnej)
- W jaki sposób kompilator może ustalić, czy dana funkcja jest czysta czy nie? (Jak w strategii sugerowane w artykule Wikipedia)
i wreszcie:
- Czy ten rodzaj optymalizacji być stosowany w dowolnym języku, lub tylko wtedy, gdy spełnione są określone warunki?
- Czy ta optymalizacja jest warta zachodu, nawet w przypadku bardzo prostych funkcji?
- Ile kosztu wiąże się ze składowaniem i pobieraniem wartości ze stosu?
Przepraszam, jeśli są to głupie lub nielogiczne pytania. To tylko niektóre rzeczy, które mnie ostatnio interesowały. :)
To się nazywa ** wspólne eliminowanie podwyrażeń ** http://en.wikipedia.org/wiki/Common_subexpression_elimination – leppie
Wydaje się, że brakuje dokumentacji dotyczącej tej opcji GNU Fortran, i podejrzewam, że generuje ona po prostu błędny kod, jeśli funkcja ma niewydajne skutki uboczne. Szybkie przeczytanie podręcznika opcji generowania kodu dla GNU Fortran poważnie wątpi w jakość ich implementacji - szczególnie takie rzeczy jak cicha umieszczanie dużej zmiennej lokalnej w pamięci statycznej ... –