Inspirowane pytaniem z SO: /programming/6623391/how-to-gain-control-of-a-5gb-heap-in-haskell
To może być długa debata na temat licznych zalet i wad FP, ale na razie chciałbym zawęzić zakres podstawowej wydajności FP na nowoczesnym sprzęcie.
Praca dyplomowa:
Paradygmat funkcjonalny zakłada niezmienność i bezpaństwowość (?), Ale sprzęt, na którym uruchamiamy programy funkcjonalne, jest stanowymi skończonymi automatami. Tłumaczenie programu „czysto funkcjonalnego” na reprezentację „stanowego sprzętu” pozostawia programistom niewielką kontrolę, powoduje obciążenie (?) I ogranicza wykorzystanie możliwości sprzętowych (?).
Czy mam rację, czy źle w kwestionowanych oświadczeniach?
Czy można udowodnić, że FP nie wiąże się z głównymi karami za wydajność w nowoczesnej architekturze komputerowej ogólnego zastosowania?
EDYCJA: Jak już powiedziałem w odpowiedzi na niektóre komentarze, pytanie nie dotyczy wydajności i szczegółów implementacji. Chodzi o obecność lub brak głównego obciążenia , które może przynieść uruchomienie FP na automatach stanowych.
running FP on stateful automata
.Odpowiedzi:
Istnieje niezrozumienie niezmienności.
Niezmienność jest cechą semantyki, ale nie implikuje niezmienności w implementacji.
Prostym przykładem jest realizacja lenistwa.
Gdy obliczenia są leniwe, wynikiem wyrażenia jest koncepcyjnie wartość, ale podstawową implementacją jest garbnik zawierający argumenty do oceny i funkcję do tworzenia wartości, a także miejsce do przechowywania wartości.
Gdy po raz pierwszy poprosisz (w języku) o wartość, obliczenie zostanie faktycznie wykonane, jego wynik oszacowany, a wartość zwrócona tobie (lub uchwytowi).
Jest to przejrzyste w semantyce języka i wszystko, co wiesz, to to, że ta zmienna została powiązana z wartością (lub wartością przyszłą) i że po jej zakończeniu nie możesz zmienić wartości, która zostanie zwrócona. Podstawowa reprezentacja pamięci zmieni się, ale nie będziesz o tym wiedzieć.
Ta sama różnica semantyczna / implementacyjna występuje w każdym języku i jest w istocie podstawą optymalizacji . Niezależnie od języka semantyka gwarantuje pewne rzeczy, ale pozostawia inne nieokreślone, aby pozostawić miejsce na optymalizację.
Prawdą jest, że praktycznie funkcjonalne języki nie są tak szybkie jak na przykład C ++. Jednak
Go
(co jest wciąż szumem) jest wolniejszy niż Haskell lub Lisp, podobnie jak C # Mono ( źródło ).Kiedy zobaczysz, jak niewiarygodne C ++ lub C może zapewnić ci te występy, możesz trochę odpuścić.
Kiedy zdasz sobie sprawę, że Haskell szybko rośnie, a wciąż jest dużo miejsca na optymalizację w jego kompilatorze / środowisku wykonawczym (GHC właśnie niedawno przeszedł na LLVM, Microsoft Research aktywnie finansuje ulepszenia środowiska uruchomieniowego), być może zechcesz się założyć, że wkrótce się poprawi.
Zabawa: Zagraj w wyrażenia regularne lub jak zespół Haskell stworzył mechanizm dopasowywania wyrażeń regularnych, który przewyższa
re2
bibliotekę C od Google, w wielu scenariuszach.źródło
Funkcjonalny paradygmat jest przydatny do dzielenia rzeczy w wąskim zakresie. To naprawdę dobra rzecz biorąc pod uwagę rozwój komputera.
Procesory wielordzeniowe mają duże problemy z zasobami współdzielonymi, a koszty synchronizacji są naprawdę drogie. Funkcjonalny paradygmat umożliwia naturalny sposób wyrażania programów, które nie mają takich problemów. To jest naprawdę dobre dla równoległości.
Ponadto coraz częściej używamy farm serwerów z SaaS i chmurą obliczeniową. Dlatego ta sama aplikacja musi działać na kilku komputerach. W tej pozycji koszty synchronizacji są jeszcze bardziej kosztowne. Google wykonał trochę pracy i opublikował kilka artykułów naukowych na temat programowania funkcjonalnego i algorytmu, w którym można pisać. Jest to dla nich kluczowe, ponieważ mają problem ze skalowalnością.
Co więcej, możesz łatwo zrobić stos na stercie komputera, a nawet nieciągły, używając połączonych list. Odbywa się to już w celu wygenerowania śledzenia stosu w wielu językach programowania. To nie jest problem.
OK, programowanie funkcjonalne wiąże się z pewnymi ograniczeniami. Ale zapewnia również naturalny sposób wyrażenia problemów, jakie mamy we współczesnym informatyce, które są niezwykle trudne do rozwiązania w paradygmatach, do których przywykliśmy. Skalowalność jest jedną z nich i staje się prawdziwą transakcją.
Wszyscy, którzy już mają do czynienia ze złożonym systemem równoległym, wiedzą o czym mówię.
Więc niuansowałbym odpowiedź. Tak, funkcjonalność ma problem z nowoczesnym sprzętem, ale ma też trochę zwykłego starego programowania. Jak zawsze znajdziesz zalety i wady. Chodzi o to, aby wiedzieć, jakie one są, abyś mógł dokonać właściwego wyboru, kiedy musisz.
źródło
Naprawdę nie mam odpowiedzi, ponieważ nie znam obecnego stanu ani nawet tego, jak trudne byłoby to, ale fakt, że kompilator zapewniłby te rzeczy z danych wejściowych, niekoniecznie oznacza, że dane wyjściowe miałyby je . Teoretycznie wystarczająco inteligentny kompilator może ominąć wszystkie te problemy, ale w praktyce prawdopodobnie zawsze będzie istniał.
Jednak innym sposobem na spojrzenie na to jest spojrzenie na historię maszyny Lisp. Jeśli dobrze pamiętam, były one pierwotnie zaprojektowane tak, aby rozwiązać te same problemy, które Lisp miał z różnicą w stosunku do maszyn w tamtym czasie. Rozwój tych maszyn ostatecznie się zatrzymał, ponieważ komputer stacjonarny stał się wystarczająco szybki, aby sprawić, że niewydajność będzie tańsza niż w przypadku obsługi innej maszyny.
Ogólnie rzecz biorąc, z wyjątkiem aplikacji najbardziej krytycznych pod względem wydajności, języki FP są wciąż wystarczająco szybkie. Wybierając dowolny język wyższego poziomu, będziesz skłonny obniżyć priorytet kontroli precyzyjnej regulacji i wydajności w celu zapewnienia bezpieczniejszego, łatwiejszego, łatwiejszego w utrzymaniu lub innego priorytetu.
Koniec końców, programowanie polega na kompromisach, więc wystarczy wybrać, co jest ważniejsze dla danego projektu.
źródło
To prawda, że paradygmat funkcjonalny zakłada niezmienność i bezpaństwowość, ale nie mamy żadnych całkowicie czystych języków programowania. Nawet najczystszy Haskell pozwala na efekty uboczne.
To powiedziawszy, aby odpowiedzieć na twoje pytanie dotyczące wydajności, użyłem zarówno Haskell, jak i Clojure, i nie zauważyłem żadnych problemów z wydajnością.
źródło