Przepraszam, jeśli jest to niejasne pytanie, ale oto:
W ciągu ostatnich kilku lat programowanie funkcjonalne cieszyło się dużym zainteresowaniem społeczności inżynierów oprogramowania. Wielu zaczęło używać języków takich jak Scala i Haskell i odniosło sukces w porównaniu z innymi językami programowania i paradygmatami. Moje pytanie brzmi: jako eksperci w dziedzinie obliczeń o wysokiej wydajności / naukowcy powinniśmy być zainteresowani programowaniem funkcjonalnym? Czy powinniśmy uczestniczyć w tej mini-rewolucji?
Jakie są zalety i wady programowania funkcjonalnego w dziedzinie pracy SciComp?
programming-paradigms
Śledztwo
źródło
źródło
Odpowiedzi:
Zrobiłem tylko trochę programowania funkcjonalnego, więc weź tę odpowiedź z odrobiną soli.
Plusy:
Cons:
Myślę, że wiele zastrzeżeń w sekcji „Wady” da się przezwyciężyć. Jak jest to częstym punktem dyskusji na tej stronie Stack Exchange, czas programisty jest ważniejszy niż czas wykonania. Nawet jeśli funkcjonalne języki programowania są powolne, jeśli części krytyczne pod względem wydajności można przekazać do szybszego języka proceduralnego i jeśli wzrost wydajności można wykazać poprzez szybki rozwój aplikacji, to warto je wykorzystać. Warto tutaj zauważyć, że programy zaimplementowane w czystym Pythonie, czystym MATLAB i czystym R są znacznie wolniejsze niż implementacje tych samych programów w C, C ++ lub Fortran. Języki takie jak Python, MATLAB i R są popularne właśnie dlatego, że zmniejszają szybkość wykonywania dla wydajności, a nawet wtedy, Zarówno Python, jak i MATLAB mają udogodnienia do implementacji interfejsów do skompilowanego kodu w C lub C ++, aby można było zaimplementować kluczowy dla wydajności kod w celu szybkiego wykonania. Większość języków ma interfejs funkcji obcych do C, co wystarczyłoby do współpracy z większością bibliotek interesujących naukowców zajmujących się obliczeniami.
Czy powinieneś być zainteresowany programowaniem funkcjonalnym?
Wszystko zależy od tego, co uważasz za fajne. Jeśli jesteś typem osoby, która jest gotowa obalić konwencję i chcesz przejść przez hasło ewangelizacji do ludzi na temat cokolwiek, co chcesz zrobić z programowaniem funkcjonalnym, powiedziałbym, że idź . Bardzo chciałbym zobaczyć, jak ludzie robią fajne rzeczy z programowaniem funkcjonalnym w nauce obliczeniowej, jeśli tylko z tego powodu, aby udowodnić, że wszyscy naysayers się mylą (i będzie wielu naysayers). Jeśli nie jesteś typem osoby, która chce poradzić sobie z grupą ludzi pytających: „Dlaczego, u diabła , używasz funkcjonalnego języka programowania zamiast (wstaw tutaj swój ulubiony język programowania proceduralnego)?”, To nie przeszkadzam.
Do prac wymagających intensywnej symulacji użyto funkcjonalnych języków programowania. Firma ilościowa Jane Street wykorzystuje OCaml do modelowania finansowego i realizacji swoich strategii handlowych. OCaml był również używany w FFTW do generowania kodu C używanego w bibliotece. Liszt to język specyficzny dla domeny opracowany w Stanford i zaimplementowany w Scali, który służy do rozwiązywania PDE. Programowanie funkcjonalne jest zdecydowanie stosowane w przemyśle (niekoniecznie w nauce obliczeniowej); okaże się, czy wystartuje w nauce obliczeniowej.
źródło
Mam może wyjątkową perspektywę, ponieważ jestem praktykiem HPC z doświadczeniem naukowym w obliczeniach, a także użytkownikiem funkcjonalnego języka programowania. Nie chcę utożsamiać HPC z obliczeniami naukowymi, ale istnieje znaczące skrzyżowanie, i taki jest punkt widzenia, w którym biorę na to pytanie.
Języki funkcjonalne raczej nie będą w tej chwili stosowane w HPC przede wszystkim dlatego, że użytkownicy i klienci HPC naprawdę dbają o osiągnięcie jak najbliższej szczytowej wydajności. Prawdą jest, że kod napisany w sposób funkcjonalny w naturalny sposób ujawnia paralelizm, który można wykorzystać, ale w HPC to nie wystarczy. Równoległość jest tylko jednym z elementów układanki w osiąganiu wysokiej wydajności, należy również wziąć pod uwagę szeroką gamę detali mikroarchitektonicznych, a wykonywanie tego na ogół wymaga bardzo drobiazgowej kontroli nad wykonywaniem kodu, kontrola ta nie jest dostępna w żadnym języki funkcjonalne, które znam.
To powiedziawszy, mam duże nadzieje, że to może się zmienić. Zauważyłem trend, że badacze zaczynają zdawać sobie sprawę, że wiele z tych mikro-architektonicznych optymalizacji można zautomatyzować (do pewnego stopnia). Spowodowało to powstanie zoo technologii kompilacji między źródłami, w której użytkownik wprowadza „specyfikację” obliczeń, które chcą mieć, a kompilator wyprowadza kod C lub Fortran, który realizuje to obliczenie z optymalizacjami i równoległością niezbędną do wydajnego działania użyj architektury docelowej. Nawiasem mówiąc, do tego dobrze funkcjonują języki funkcjonalne: modelowanie i analiza języków programowania. To nie przypadek, że pierwszymi głównymi użytkownikami języków funkcjonalnych byli twórcy kompilatorów. Z kilkoma znaczącymi wyjątkami, nie widziałem, aby to się faktycznie trzymało, ale pomysły już istnieją,
źródło
Chciałbym dodać jeden aspekt do pozostałych dwóch odpowiedzi. Poza ekosystemem programowanie funkcjonalne stanowi doskonałą okazję do równoległego wykonywania, takiego jak wielowątkowość lub przetwarzanie rozproszone. Jego nieodłączne właściwości niezmienności sprawiają, że nadaje się on do równoległości, która generalnie jest prawdziwym bólem w * bleep *, jeśli chodzi o języki imperatywne.
Ponieważ poprawa wydajności sprzętu w ostatnich latach koncentrowała się na dodawaniu rdzeni do procesorów zamiast na zwiększaniu częstotliwości, obliczenia równoległe stają się coraz bardziej popularne (założę się, że wszyscy o tym wiedzą).
Inną rzeczą, o której wspomina Geoff, jest to, że czas programisty jest często ważniejszy niż czas wykonania. Pracuję dla firmy, która buduje intensywny obliczeniowo SaaS i przeprowadziliśmy wstępny test wydajności, zaczynając od C ++ vs Java. Okazało się, że C ++ zapewnia około 50% skrócenie czasu wykonania w stosunku do Java (dotyczyło to geometrii obliczeniowej, a liczby najprawdopodobniej będą się różnić w zależności od aplikacji), ale i tak poszliśmy z Javą ze względu na znaczenie czasu programisty i mieliśmy nadzieję, że optymalizacje i przyszłe ulepszenia wydajności sprzętu pomogłyby nam wejść na rynek. Mogę powiedzieć z pewnością, że gdybyśmy wybrali inaczej, nie prowadzilibyśmy działalności.
Ok, ale Java nie jest funkcjonalnym językiem programowania, więc co może mieć z tym wspólnego, możesz zapytać. Później, kiedy zatrudniliśmy więcej zwolenników paradygmatu funkcjonalnego i natknęliśmy się na potrzebę paralellizacji, stopniowo migrowaliśmy części naszego systemu do Scali, która łączy pozytywne aspekty programowania funkcjonalnego z siłą imperatywu i dobrze łączy się z Jawa. Ogromnie pomógł nam, zwiększając wydajność naszego systemu przy minimalnym bólu głowy i prawdopodobnie nadal będzie czerpał korzyści z dalszego wzrostu wydajności w branży sprzętowej, gdy więcej rdzeni zostanie wciśniętych w procesory jutra.
Zauważ, że całkowicie zgadzam się z wadami wymienionymi w innych odpowiedziach, ale pomyślałem, że ułatwienie równoległego wykonywania jest tak potężnym profesjonalistą, że nie można go pominąć.
źródło
Geoff przedstawił już dobry przegląd powodów, do których niewiele dodałem, oprócz podkreślenia jednego z jego punktów: ekosystemu. Niezależnie od tego, czy opowiadasz się za programowaniem funkcjonalnym, czy za jakimkolwiek innym paradygmatem, jednym z ważnych pytań, na które musisz odpowiedzieć, jest to, że istnieje niesamowita ilość oprogramowania, z którego każda inna osoba może zbudować, którą musisz ponownie napisać. Przykładami są MPI, PETSc lub Trilinos dla algebry liniowej lub dowolnej biblioteki elementów skończonych - wszystkie napisane w C lub C ++. W systemie występuje ogromna bezwładność, może nie dlatego, że wszyscy uważają, że C / C ++ jest w rzeczywistości najlepszym językiem do pisania oprogramowania obliczeniowego, ale ponieważ wiele osób spędzało lata życia, tworząc coś, co jest przydatne dużo ludzi.
Myślę, że większość ludzi obliczeniowych zgodzi się, że wypróbowanie nowych języków programowania i ocena ich przydatności do tego problemu jest bardzo cenna. Ale będzie to trudny i samotny czas, ponieważ nie będziesz w stanie osiągnąć wyników, które byłyby konkurencyjne w stosunku do tego, co robią wszyscy inni. Może również przynieść ci reputację kogoś, kto rozpoczął następny krok do innego paradygmatu programistycznego. Hej, zastąpienie Fortran zajęło C ++ około 15 lat!
źródło
Oto krótkie podsumowanie
Te fakty razem sprawiają, że programowanie funkcjonalne nie wydaje się konieczne dla większości użytkowników.
źródło
Myślę, że warto zauważyć, że zastosowanie programowania funkcjonalnego w nauce obliczeniowej nie jest nowe. Na przykład w tym dokumencie z 1990 r. Pokazano, jak poprawić wydajność programów numerycznych napisanych w Lisp (prawdopodobnie najwcześniejszym funkcjonalnym języku programowania) przy użyciu częściowej oceny. Praca ta była częścią łańcucha narzędzi stosowanego w artykule z 1992 r. Autorstwa GJ Sussmana ( znanego z SICP ) i J Wisdom, który dostarczył liczbowych dowodów na chaotyczne zachowanie Układu Słonecznego . Więcej informacji o sprzęcie i oprogramowaniu uczestniczącym w tych obliczeniach można znaleźć tutaj .
źródło
R jest językiem funkcjonalnym, a także językiem statystycznym (i teraz uczeniem maszynowym), a właściwie językiem numer 1 dla statystyk. Nie jest to jednak język HPC: nie jest on używany do tradycyjnego „łamania liczb”, takiego jak symulacje fizyki itp. Można go jednak uruchomić na masywnych klastrach (np. Przez MPI) do masowych symulacji statystycznych (MCMC) uczenia maszynowego.
Mathematica jest także językiem funkcjonalnym, ale jego podstawową domeną jest przetwarzanie symboliczne, a nie obliczenia numeryczne.
W Julii możesz także programować w funkcjonalnym stylu (obok procedur i ich smaku OO (multi-dispatch)), ale nie jest to czyste (wszystkie podstawowe struktury danych są zmienne (z wyjątkiem krotek), chociaż istnieją pewne biblioteki z niezmiennymi funkcjonalne struktury danych. Co ważniejsze, jest znacznie wolniejsze niż styl proceduralny, więc nie jest często używane.
Nie nazwałbym Scali językiem funkcjonalnym, a raczej hybrydą obiektowo-funkcjonalną. W Scali można używać wielu koncepcji funkcjonalnych. Scala jest ważna w chmurze obliczeniowej ze względu na Spark ( https://spark.apache.org/ ).
Zauważ, że współczesny Fortran ma w rzeczywistości pewne elementy programowania funkcjonalnego: ma ścisłą semantykę wskaźnika (w przeciwieństwie do C), możesz mieć czyste (bez efektów ubocznych) funkcje (i oznaczyć to jako takie) i możesz mieć niezmienność. Ma nawet inteligentne indeksowanie, w którym można określić warunki dla indeksów macierzowych. Jest to zapytanie podobne i zwykle spotykane tylko w języku wysokiego poziomu, takim jak R LINQ w języku C # lub poprzez funkcje filtrów wyższego rzędu w językach funkcjonalnych. Tak więc Fortran wcale nie jest taki zły, ma nawet całkiem nowoczesne funkcje (np. Wspólne tablice), których nie ma w wielu językach. W rzeczywistości w przyszłych wersjach Fortran wolałbym raczej dodawać więcej funkcji funkcjonalnych niż funkcje OO (co obecnie ma miejsce zwykle), ponieważ OO w Fortran jest naprawdę niezręczny i brzydki.
źródło
Plusy to „narzędzia” wbudowane w każdy język funkcjonalny: filtrowanie danych jest tak łatwe, iteracja danych jest łatwiejsza, a znalezienie łatwiejszego i bardziej zwięzłego rozwiązania problemów jest o wiele łatwiejsze.
Jedynym minusem jest to, że musisz skupić się na nowym sposobie myślenia: zajęło trochę czasu, aby dowiedzieć się, co musisz wiedzieć. Inni w domenie SciComp tak naprawdę nie używają tych języków, co oznacza, że nie można uzyskać tak dużego wsparcia :(
Jeśli interesują Cię języki funkcjonalne-naukowe, opracowałem jeden https://ac1235.github.io
źródło
Oto moje argumenty przemawiające za tym, dlaczego programowanie funkcjonalne może i powinno być wykorzystywane w nauce obliczeniowej. Korzyści są ogromne, a wady szybko znikają. Moim zdaniem jest tylko jeden oszust:
Wada : brak obsługi języka w C / C ++ / Fortran
Przynajmniej w C ++ ta zniknie - ponieważ C ++ 14/17 dodał potężne narzędzia do obsługi programowania funkcjonalnego. Być może będziesz musiał napisać kod biblioteki / wsparcia samodzielnie, ale językiem będzie twój przyjaciel. Jako przykład podajemy bibliotekę (ostrzeżenie: wtyczka), która wykonuje niezmienne wielowymiarowe tablice w C ++: https://github.com/jzrake/ndarray-v2 .
Oto link do dobrej książki na temat programowania funkcjonalnego w C ++, chociaż nie jest on skoncentrowany na aplikacjach naukowych.
Oto moje podsumowanie tego, co według mnie jest profesjonalistą:
Plusy :
Jeśli chodzi o poprawność , programy funkcjonalne są wyraźnie dobrze postawione : zmuszają cię do prawidłowego zdefiniowania minimalnego stanu zmiennych fizycznych oraz funkcji, która przesuwa ten stan do przodu w czasie:
Rozwiązanie równania różniczkowego cząstkowego (lub ODE) jest idealne do programowania funkcjonalnego; po prostu zastosujesz czystą funkcję (
advance
) do bieżącego rozwiązania, aby wygenerować następne.Z mojego doświadczenia wynika, że oprogramowanie do symulacji fizyki jest zasadniczo obciążone złym zarządzaniem stanem . Zwykle każdy etap algorytmu działa na pewnym stanie wspólnego (efektywnie globalnego) stanu. Utrudnia to, a nawet uniemożliwia, zapewnienie prawidłowej kolejności operacji, pozostawiając oprogramowanie podatne na błędy, które mogą objawiać się jako błędy seg, lub, co gorsza, warunki błędów, które nie powodują awarii kodu, ale dyskretnie naruszają integralność jego wiedzy wynik. Próba zarządzania stanem współdzielonym w symulacji fizyki również hamuje wielowątkowość - co stanowi problem na przyszłość, ponieważ superkomputery zmierzają w kierunku większej liczby rdzeni, a skalowanie z MPI często kończy się na ~ 100 tys. Zadań. Natomiast programowanie funkcjonalne sprawia, że paralelizm pamięci współużytkowanej jest trywialny ze względu na niezmienność.
Wydajność poprawia się również w programowaniu funkcjonalnym ze względu na leniwą ocenę algorytmów (w C ++ oznacza to generowanie wielu typów w czasie kompilacji - często po jednym dla każdej aplikacji funkcji). Ale zmniejsza obciążenie dostępu do pamięci i przydziałów, a także eliminuje wirtualną wysyłkę - pozwalając kompilatorowi zoptymalizować cały algorytm, widząc jednocześnie wszystkie obiekty funkcyjne, które go zawierają. W praktyce będziesz eksperymentować z różnymi ustawieniami punktów oceny (w których wynik algorytmu jest buforowany do bufora pamięci), aby zoptymalizować wykorzystanie procesora w porównaniu do alokacji pamięci. Jest to raczej łatwe ze względu na dużą lokalizację (patrz przykład poniżej) etapów algorytmu w porównaniu z tym, co zwykle zobaczysz w module lub kodzie opartym na klasach.
Programy funkcjonalne są łatwiejsze do zrozumienia, o ile trywializują stan fizyki. Nie oznacza to, że ich składnia jest zrozumiała dla wszystkich twoich kolegów! Autorzy powinni zachować ostrożność przy korzystaniu z dobrze nazwanych funkcji, a badacze powinni przyzwyczaić się do tego, że algorytmy są wyrażane funkcjonalnie, a nie proceduralnie. Przyznaję, że brak struktur kontrolnych może być dla niektórych zniechęcający, ale nie sądzę, że powinno to powstrzymywać nas przed pójściem w przyszłość, by móc robić lepszą naukę na komputerach.
Poniżej znajduje się przykładowa
advance
funkcja, zaadaptowana z kodu o skończonej objętości za pomocąndarray-v2
pakietu. Zwróć uwagę nato_shared
operatory - są to punkty oceny, o których wspominałem wcześniej.źródło