2013-02-26 11 views
12

Rozważmy tę funkcję:Czy optymalizator Haskell wykorzystuje zapamiętywanie dla powtarzających się wywołań funkcji w zakresie?

f as = if length as > 100 then length as else 100 

Ponieważ funkcja jest czysta to oczywiste, że długość będzie taka sama w obu połączeń. Moje pytanie brzmi: czy optymalizator Haskella zamienia powyższy kod na odpowiednik poniższych?

f as = 
    let l = length as 
    in if l > 100 then l else 100 

Jeśli tak, to jakie ustawienie poziomu to umożliwia? Jeśli nie, to dlaczego? W tym scenariuszu marnowanie pamięci nie może być przyczyną wyjaśnioną w this answer, ponieważ wprowadzona zmienna zostanie zwolniona zaraz po zakończeniu wykonywania funkcji.


Należy pamiętać, że to nie jest duplikatem this question powodu zasięgu lokalnym, a tym samym może dostać zupełnie inną odpowiedź.

Odpowiedz

15

GHC ma teraz some CSE by default, ponieważ flaga -fcse jest włączona.

Domyślnie włączone. Włącza optymalizację wspólnej eliminacji podrzędnej . Wyłączenie tego może być przydatne, jeśli masz jakieś niebezpieczne wyrażenia unsafePerformIO, których nie chcesz upowszechniać.

Jednak jest to conservative, ze względu na problemy z udostępnianiem (a zatem przecieki kosmiczne). Jednak przepustka CSE uzyskuje wartość bit better (i this).

Wreszcie, należy pamiętać, że istnieje wtyczka do pełnej wersji CSE.

Jeśli masz kod, który może skorzystać z tego.

13

Nawet w takim otoczeniu lokalnym, nadal nie jest oczywiste, że wprowadzenie udostępniania jest zawsze optymalizacją. Rozważmy następujący przykład definicję

f = if length [1 .. 1000000] > 0 then head [1 .. 1000000] else 0 

vs. ten

f = let xs = [1 .. 1000000] in if length xs > 0 then head xs else 0 

a przekonasz się, że w tym przypadku, pierwszy zachowuje się znacznie lepiej, a każdy z obliczeń wykonanych na liście jest tanie, podczas gdy druga wersja spowoduje, że lista zostanie całkowicie rozwinięta w pamięci przez length, i może zostać usunięta dopiero po zmniejszeniu wartości head.

+3

Mimo tego problemu ghc może być znacznie bardziej agresywny w przypadku CSE. Musisz tylko oszacować wartość wartości CSE. Prostym oszacowaniem jest, że typy bazowe zajmują pomijalne miejsce. – augustss

+0

@augustss Zgoda. – kosmikus

+0

W jaki sposób 'length [1 .. 1000000]> 0' jest tanią operacją? Czy "długość" nie powróci zanim ">" zostanie ocenione?(W ghci operacja jest spowolniona zauważalnie, gdy zwiększam rozmiar listy) –