Czy paradygmat funkcjonalny nie jest zbyt rozbieżny z podstawowym sprzętem, aby był ogólnie wydajny?


14

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.


3
Czy naprawdę zastanawiałeś się kiedyś, jak działa nowoczesny sprzęt na niskim poziomie? Jeśli w ogóle zależy Ci na wydajności, nie przypomina ona codziennego programowania imperatywnego.
CA McCann,

Wierzcie lub nie, ale informatycy, którzy zaprojektowali funkcjonalne języki programowania i kompilatory, również wiedzą trochę na temat optymalizacji wydajności. Nie jest to celem każdego funkcjonalnego produktu językowego, ale dotyczy poważnych platform produkcyjnych.
Jeremy

Na przykład @camccann, @Jeremy: C # i Java używają maszyn wirtualnych. Bez względu na to w jaki sposób optymalny to jest, bez względu na to, jak skuteczne programy C # i Java są do produkcji, nie jest głównym źródłem nieefektywności, i jest to VM. Pytanie nie dotyczy wydajności wdrożenia, ale running FP on stateful automata.
winorośl


2
@ vines: Zdajesz sobie sprawę, że nowoczesne maszyny wirtualne z fantazyjnym JITingiem w niektórych przypadkach mogą faktycznie przewyższać natywny kod, prawda? I że głównym celem kompilatora jest konwersja programu do reprezentacji pasującej do architektury bazowej, co różni się od współczesnego języka? Twoje pytanie nie ma sensu.
CA McCann,

Odpowiedzi:


7

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 re2bibliotekę C od Google, w wielu scenariuszach.


Brzmi optymistycznie :)
winorośle

3

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.


0

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.


0

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ą.


1
Problemy dotyczą wymagań ... Co z obszarami o kluczowym znaczeniu dla wydajności? Wysoki paralelizm jest tam cenny, ale jaki jest ogólny wynik?
winorośl

1
@vines: Nie użyłem żadnego języka dla aplikacji krytycznej pod względem wydajności, więc tak naprawdę nie mogę z tym rozmawiać.
Larry Coleman

1
Niewiele zabawy bez żadnych skutków ubocznych, ponieważ nigdzie nie można zapisać wyniku.

@ Thorbjørn Ravn Andersen: ... w inny sposób niż zwracanie go dzwoniącemu, co jest dozwolone.
winorośl
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.