Chcę opracować od podstaw równoległe oprogramowanie do obliczeń naukowych. Chcę się zastanowić, od którego języka zacząć. Program obejmuje odczytywanie / zapisywanie danych do plików txt i wykonywanie ciężkich obliczeń równolegle, z wieloma faktoryzacjami LU i wykorzystaniem rzadkich liniowych solverów. Rozwiązania, o których myślałem, to Fortran 2003/2008 z OpenMP lub co-array, C ++ z openmp cilk + lub TBB, python. Wszelkie inne udokumentowane sugestie są mile widziane! Znam bardzo dobrze C, Fortran i Java (w tej kolejności). Zrobiłem trochę skryptów w Pythonie, ale podstawowe rzeczy.
Wiem, że fortran jest bardzo szybki, ale trudny w utrzymaniu i równoległym. Mówi się, że C ++ działa wolno, chyba że używasz zewnętrznych bibliotek itp. Python mi się podoba, ale czy realistyczne jest pisanie pełnego oprogramowania na poziomie przemysłowym?
Oprogramowanie musi być w stanie obsłużyć duże ilości danych i być skuteczne w obliczeniach naukowych. Wydajność jest najważniejsza.
W tle mam już działające oprogramowanie napisane w Fortranie. Wiele osób było zaangażowanych w rozwój przez wiele lat, a kod jest naprawdę brudny. Utrzymanie i równoległość kodu okazało się koszmarem i myślę o alternatywach.
Petros
Odpowiedzi:
Pozwól mi spróbować rozbić twoje wymagania:
Z tej listy rozważyłbym następujące języki:
C, C ++, Fortran, Python, MATLAB, Java
Julia jest obiecującym nowym językiem, ale społeczność wciąż się wokół niego tworzy i nie została wdrożona w żadnych nowych kodach.
Odczytywanie / zapisywanie danych tekstowych
Łatwo to uzyskać w dowolnym języku programowania. Upewnij się, że odpowiednio buforujesz i łączysz dostęp do wejść / wyjść, a uzyskasz dobrą wydajność w każdym z języków, które powinieneś rozważyć. Unikaj obiektów strumieniowych w C ++, chyba że wiesz, jak ich używać skutecznie.
Silne interfejsy / możliwości dla faktoryzacji LU
Jeśli wykonujesz gęstą faktoryzację LU, będziesz chciał użyć LAPACK lub ScaLAPACK / Elemental do równoległej funkcjonalności. LAPACK i ScaLAPACK są napisane w Fortran, Elemental w C ++. Wszystkie trzy biblioteki są wydajne, dobrze obsługiwane i dokumentowane. Możesz się do nich komunikować z dowolnego języka, który powinieneś rozważyć.
Rzadkie solwery liniowe
Najlepsze, swobodnie dostępne rzadkie solwery liniowe są prawie wszystkie dostępne za pośrednictwem PETSc , napisanego w C, który jest dobrze udokumentowany i obsługiwany. Możesz połączyć się z PETSc z dowolnego języka, który powinieneś rozważyć.
Wydajność i skalowalność do dużych danych
Jedynymi paradygmatami programowania równoległego, o których wspomniałeś, są oparte na pamięci współdzielonej, co oznacza, że nie rozważasz podejścia obliczeniowego opartego na MPI (przekazywanie komunikatów) i pamięci rozproszonej. Z mojego doświadczenia wynika, że o wiele łatwiej jest pisać kod, który skaluje się znacznie poza kilkanaście rdzeni za pomocą rozwiązania pamięci rozproszonej. Prawie wszystkie „klastry” uniwersyteckie są obecnie oparte na MPI, duże maszyny z pamięcią współdzieloną są drogie i odpowiednio rzadkie. Powinieneś rozważyć MPI dla swojego podejścia, ale moja rada będzie obowiązywać niezależnie od wybranego paradygmatu programowania.
Jeśli chodzi o wydajność w węźle, jeśli sam piszesz procedury numeryczne, najłatwiej jest uzyskać dobrą wydajność szeregową w Fortranie. Jeśli masz trochę doświadczenia w C, C ++ lub Python, możesz uzyskać bardzo porównywalną wydajność (C i C ++ są martwe - nawet z Fortranem, Python i MATLAB są o około 25% czasochłonne bez większego wysiłku). MATLAB robi to za pomocą kompilatora JIT i bardzo dobrej ekspresji algebry liniowej. Najprawdopodobniej będziesz musiał użyć jądra numerycznego Cython, numpy, numexpr lub embed, aby uzyskać deklarowaną wydajność z Pythona. Nie mogę komentować wydajności Javy, ponieważ nie znam dobrze języka, ale podejrzewam, że nie jest on daleko od Pythona, jeśli jest napisany przez eksperta.
Uwaga na temat interfejsów
Mam nadzieję, że przekonałem cię, że będziesz w stanie zrobić wszystko, co chcesz, w dowolnym z rozważanych języków programowania. Jeśli używasz Java, interfejsy C będą nieco trudne. Python ma doskonałą obsługę interfejsu C i Fortran poprzez ctypes, Cython i f2py. LAPACK jest już zapakowany i dostępny przez scipy. MATLAB ma wszystkie potrzebne funkcje w swoich bibliotekach natywnych, ale nie jest łatwo skalowalny ani szczególnie łatwy do uruchomienia w klastrach. Java może obsługiwać interfejsy C i Fortran z JNI , ale nie jest powszechnie spotykana w klastrach i równoległym oprogramowaniu do obliczeń naukowych.
Konserwowalność
Wiele z tego sprowadza się do osobistego gustu, ale ogólny konsensus co do łatwości konserwacji jest taki, że chcesz zminimalizować liczbę linii kodu w swoim oprogramowaniu, pisać kod modułowy z dobrze zdefiniowanymi interfejsami, a dla oprogramowania obliczeniowego zapewnić testy weryfikujące poprawność i funkcjonalność wdrożenia.
Rekomendacje
Ja osobiście nie miałem dużo szczęścia z Python i polecam go do wielu projektów obliczeniowych. Myślę, że powinieneś zdecydowanie rozważyć to w swoim projekcie. Python i MATLAB są prawdopodobnie najbardziej wyrazistymi językami dostępnymi w informatyce naukowej. Możesz łatwo interfejsować Python z dowolnym innym językiem programowania, możesz użyć f2py, aby owinąć swoją obecną implementację Fortrana i kawałek po kawałku przepisać dowolne części w Pythonie, jednocześnie sprawdzając, czy zachowujesz funkcjonalność. W tej chwili poleciłbym połączenie oficjalnej implementacji Python 2.7 z scipy . Możesz bardzo łatwo zacząć z tym stosem z bezpłatnej dystrybucji Enthought Python Distribution .
Możesz to zrobić w większości w C, C ++ lub Fortran. C i C ++ są bardzo atrakcyjnymi językami dla profesjonalnych programistów z dużym doświadczeniem, ale często podróżują z nowymi programistami i w tym sensie prawdopodobnie nie są świetnym pomysłem na bardziej akademicki kod. Fortran i MATLAB są popularne w obliczeniach akademickich, ale są słabe, jeśli chodzi o zaawansowane struktury danych i ekspresję, które oferuje Python (na przykład pomyśl o obiekcie dict w Pythonie).
Powiązane pytania:
źródło
Oprócz bardzo wyczerpującej odpowiedzi Arona przyjrzałbym się różnym wątkom na scicomp.stackexchange, które zajmowały się pytaniem, który język programowania wybrać - zarówno w odniesieniu do szybkości programów, jak i pytania, jak łatwe lub trudne jest pisanie i utrzymywanie oprogramowania w tych językach.
To powiedziawszy, oprócz tego, co tam zostało napisane, pozwól mi poczynić kilka uwag:
(i) Uwzględniasz Fortran na swojej tablicy. O ile mi wiadomo, liczba kompilatorów, które faktycznie go obsługują, jest bardzo mała - a ja w rzeczywistości wynosi zero. Najbardziej powszechnie dostępnym kompilatorem Fortran jest GNU gfortran i chociaż obecne źródła programistyczne analizują podzbiór wspólnych tablic, uważam, że tak naprawdę nie obsługuje żadnego z nich (tzn. Akceptuje składnię, ale nie implementuje żadnej semantyki) . Jest to oczywiście ogólna obserwacja dotycząca nowszych standardów Fortran: że opóźnienie, z jakim kompilatory faktycznie obsługują nowe standardy, jest mierzone w ciągu kilku lat - kompilatory w pełni wdrożyły Fortran 2003 w ciągu ostatnich kilku lat i tylko częściowo obsługują Fortran 2008. Nie powinno to powstrzymywać Cię przed korzystaniem z niego, jeśli masz kompilator obsługujący to, czego używasz,
(ii) To samo z pewnością jest prawdą w przypadku C ++ / Cilk +: Tak, Intel rozwija to w gałęzi GCC, ale nie jest dostępny w żadnej z wersji GCC i prawdopodobnie nie będzie przez jakiś czas. Możesz spodziewać się, że minie kolejne 2-3 lata, zanim znajdziesz Cilk + z wersjami GCC zainstalowanymi na typowych komputerach z systemem Linux.
(iii) C ++ / TBB to inna historia: TBB istnieje już od jakiegoś czasu, ma bardzo stabilny interfejs i jest kompatybilny z większością dowolnych kompilatorów C ++, które istniały przez kilka ostatnich lat (zarówno w systemie Linux, jak i Windows) . Używamy go w umowie. II już od kilku lat z dobrymi wynikami. Jest tam również bardzo dobra książka.
(iv) Mam własne zdanie na temat OpenMP, a mianowicie, że jest to rozwiązanie w poszukiwaniu problemu. Działa dobrze do równoległego tworzenia wewnętrznych pętli, co może być interesujące, jeśli masz bardzo regularne struktury danych. Ale rzadko jest to, co chcesz zrobić, jeśli chcesz coś zrównoleglić - ponieważ tak naprawdę chcesz to zrównoważyć zewnętrzne pętle. I do tego rozwiązania takie jak TBB są znacznie lepszymi rozwiązaniami, ponieważ wykorzystują mechanizmy języka programowania, zamiast próbować opisać, co dzieje się poza tym językiem (przez #pragmas) i w taki sposób, że nie masz dostępu do uchwytów wątków , wskaźniki statusu wyników itp. z poziomu programu.
(v) Jeśli jesteś eksperymentalny, możesz także zapoznać się z nowymi językami programowania zaprojektowanymi do programowania równoległego, a zwłaszcza do zadań takich jak te, które opisujesz. Zasadniczo są dwa: X10 i Chapel . Widziałem fajne samouczki na temat Chapel i wydaje się, że są dobrze zaprojektowane, choć oba oczywiście są również rozwiązaniami wyspiarskimi.
źródło
Ogólnie rzecz biorąc, jeśli naprawdę poważnie podchodzisz do tego projektu oprogramowania, sugerowałbym całkowite przepisanie w dowolnym języku, w którym czujesz się najlepiej. Wygląda na to, że będziesz wykonywał pracę samodzielnie, dzięki czemu uzyskasz najlepsze wyniki w języku, w którym czujesz się najlepiej w domu.
Mówiąc dokładniej, jeśli chodzi o paralelizm, zachęcam do spróbowania myślenia nieco poza schematem. OpenMP ma swoje mocne strony, ale utknął w myśleniu o sekwencyjnym kodzie i uderzaniu w paralelizm tu i tam. To samo dotyczy Intels TBB.
Cilk jest zdecydowanie krokiem we właściwym kierunku, tj. Zmusza cię do ponownego przemyślenia problemu / rozwiązania w z natury równoległej konfiguracji. Jednak nie podoba mi się to, że jest to kolejny język . Ponadto, ponieważ może jedynie z grubsza wywnioskować relacje między równoległymi zadaniami, harmonogram może być dość konserwatywny i może nie być dobrze skalowany dla niektórych problemów.
Dobrą wiadomością jest to, że ponownie, jeśli poważnie podchodzisz do swojej implementacji, możesz zrobić to, co robi Cilk, np. Ponownie napisać swój problem jako zestaw wzajemnie zależnych zadań i rozdzielić je na kilka procesorów / rdzenie, wszystkie na własną rękę, używając pthreads lub niewłaściwie wykorzystując OpenMP do odradzania procesów. Dobrym przykładem tego, jak można to zrobić, jest harmonogram QUARK używany w bibliotece PLASMA . Ładne porównanie jego wydajności w porównaniu z Cilkiem znajduje się tutaj .
źródło
pthreads-win32
lub w ramachcygwin
projektu.W powyższych komentarzach niewiele dyskutowano o coarray fortran. Obecnie, i o mojej ograniczonej wiedzy, obsługa macierzy w kompilatorach wygląda mniej więcej tak:
Ogólnie rzecz biorąc, byłbym ostrożny, gdyby uruchamiał kod oparty na macierzy podstawowej. Składnia jest prosta i znacznie wygodniejsza niż Fortran / C / C ++ z MPI, ale nie jest tak w pełni funkcjonalna. Na przykład MPI obsługuje wiele operacji redukcji itp., Które mogą być dla ciebie bardzo wygodne. To naprawdę zależy od potrzeby dużej komunikacji. Jeśli chcesz przykład, daj mi znać, a ja dam ci kilka, jeśli mogę wykopać pliki.
źródło
Spójrz na Spark to rozproszona platforma do obliczeń w pamięci, która wykorzystuje funkcjonalne programowanie. Struktura programu w Spark jest bardzo różna w porównaniu do MPI, w zasadzie piszesz kod jak dla pojedynczego komputera, który jest automatycznie dystrybuowany jako funkcje do danych znajdujących się w pamięci. Obsługuje Scala, Java i Python.
Regresja logistyczna (scala):
Istnieje rozszerzenie o nazwie MLib (biblioteka uczenia maszynowego), która wykorzystuje bibliotekę Fortran do niektórych obliczeń niskiego poziomu (w Pythonie chyba używa się numpy). Pomysł jest więc prosty, skoncentruj się na algorytmie i pozostaw optymalizacje na niższych poziomach (kolejność przetwarzania, dystrybucja danych itp.).
źródło