Język programowania równoległego obliczeń naukowych?


18

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


5
Jako wink C ++ nie nazwałbym Fortrana trudnym do utrzymania. Utrzymywalność jest w przeważającej części związana z dobrymi praktykami, a nie z wyborem języka. Powolność C ++ jest wyprzedana. Polecam również ulepszyć ten post, aby opisać rozmiar danych i wymagania dotyczące czasu realizacji. Widziałem, że „duże” różnią się o 9 lub 10 rzędów wielkości w zależności od tego, z kim rozmawiam.
Bill Barth

@BillBarth Problem z istniejącym kodem Fortran polega na tym, że trzy osoby były zaangażowane w stosowanie różnych praktyk. Pochodzę z klasy C, jeden facet z F77 i inny facet z Matlaba. Dane nie mogą być przydzielane i sortowane dla największego systemu wielkości (byłem ostatnio zaangażowany). Kod był w stanie symulować układ z 72000 różnicami i 74000 równań algebraicznych w horyzoncie czasowym 240s w 350s (czas, który upłynął). Zmniejszyłem to do 170s, używając OpenMP do zrównoleglenia. Teraz muszę uruchomić kilka spraw równolegle (w celu sprawdzenia bezpieczeństwa).
electrique

4
@BillBarth jest zbyt skromny, sprzedając swoje umiejętności C ++, ale jest również zbyt hojny w swoim oświadczeniu, że „powolność C ++ jest nadmierna”. W scicomp.stackexchange.com pojawiło się wiele wątków C ++ w porównaniu z Fortranem, które omawiały to samo pytanie i ogólny wniosek był taki, że po prostu nie jest prawdą, że C ++ jest wolniejszy niż Fortran w prawie wszystkich przypadkach. Osobiście uważam, że dziś można go uznać za mit miejski. Co jest bardzo prawdziwe jest to, że jeśli wziąć pod uwagę łatwość konserwacji kodu, a następnie Fortran nie radzą sobie bardzo dobrze dzisiaj.
Wolfgang Bangerth

2
@BillBarth i inni, jeśli chcesz nadal omawiać ogólne zalety Fortran, C ++ i innych języków, zabierz go do pokoju rozmów scicomp i do @ każdego, z kim chcesz się konkretnie skontaktować .
Aron Ahmadia,

1
@AronAhmadia: ah, daj spokój, mam tak wiele do powiedzenia Jedowi ;-) (Jed: kiedyś. W naszym przypadku nie ma STL dla rzadkich macierzy, ale dużo w adaptacyjnych strukturach danych siatki.)
Wolfgang Bangerth,

Odpowiedzi:


19

Pozwól mi spróbować rozbić twoje wymagania:

  • Konserwowalność
  • Odczytywanie / zapisywanie danych tekstowych
  • Silne interfejsy / możliwości dla faktoryzacji LU
  • Rzadkie solwery liniowe
  • Wydajność i skalowalność do dużych danych

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:


1
Bardzo dobrze udokumentowana, kompleksowa odpowiedź. Pod Fortranem używam dużo Lapacka. Rzucę okiem na Python i staram się owinąć kod Fortran na początek i powoli powoli przejść do Pythona. Jedyną rzeczą, która mnie przeraża, jest 25% czas, jaki mogę mieć. Ale jeśli przyniesie to korzyści z bardziej ekspresyjnego kodu i lepszej obsługi obliczeń równoległych, skorzystam z tego. Wspomniałem o pamięci współdzielonej tylko dlatego, że oprogramowanie działa obecnie w sposób interaktywny (zmień dane i uruchom ponownie) na 2,4,8,24,48-rdzeniowych komputerach z pamięcią współdzieloną badaczy w Uni pod Windows i Linux.
electrique

3
Nie wiem, jak można domagać się 25% narzutu na jądra numeryczne napisane w Pythonie. Jądra numeryczne w czystym języku Python są często o 100 razy wolniejsze niż C. Numpy i numexpr mogą wykonywać przyzwoite zadania z pewnymi wyrażeniami, ale to prawie nie pisze nowych jąder numerycznych w Pythonie. Cython potrafi szybko robić pewne rzeczy, ale zwykle nie w 25% C. Python jest dobrym językiem „kleju”, ale myślę, że Aron przecenia go jako rozwiązanie ogólnego przeznaczenia do zadań wrażliwych na wydajność.
Jed Brown

I / O jest słabym punktem Fortrana, ponieważ Fortran wymaga dużej struktury we / wy. Moje doświadczenia z drugiej ręki podczas rozmowy z kolegami z mojego laboratorium, którzy pracują z Cython, pasują do tego, co Jed mówi o Cython; przynajmniej jeden z nich pisze ręcznie dostrojony C, aby zastąpić Cython w zadaniach wymagających dużej wydajności, a następnie uważam, że wydajność wywołania przez Python wynikowego kodu C jest bliższa twierdzeniu Arona. Ponadto, jeśli zamierzasz wspomnieć o PETSc i Pythonie, możesz równie dobrze wspomnieć o petsc4py. Ostatnio widziałem (to było kilka lat temu), że nie było dobrych interfejsów MPI dla Javy. Czy to się zmieniło?
Geoff Oxberry

@GeoffOxberry: Powiązania Java MPI istnieją, ale nie były aktualizowane od prawie dekady. Uważam ich status za wątpliwy. Fortran ma wiele opcji We / Wy, które można bardzo szybko uruchomić. Polecam eksplorację Parallel HDF5 (i HDF5, ogólnie). Jeśli we / wy jest naprawdę dominujące (ponad 50% czasu działania), mogą być bardziej poważne środki, ale w przeciwnym razie jakość i przenośność interfejsu HDF jest prawdopodobnie tego warta.
Bill Barth

@BillBarth: Muszę to sprawdzić. Mój komentarz na temat Fortran I / O pochodzi z punktu widzenia kogoś, kto kiedyś zalecił napisanie parsera plików wejściowych w Fortran. Jest to możliwe poprzez wymuszenie dużej ilości struktur, ale po prostu nie widziałem w Fortranie łatwego i szeroko stosowanego parsera wyrażeń regularnych lub bibliotek parsera XML (aby podać kilka przykładów). Jest ku temu dobry powód: jesteśmy jedynymi ludźmi korzystającymi z Fortranu. Być może myślimy o różnych przypadkach użycia.
Geoff Oxberry

2

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.


Dla przypomnienia, Intel twierdzi, że ma wbudowaną równoległą (pamięć rozproszoną) macierz Fortran wbudowaną w ich obecne kompilatory. Przyglądamy się temu w TACC, ale nie mam jeszcze nic do zgłoszenia. Cray ma również implementację w swoim kompilatorze, ale jest ona dostępna tylko na małej liczbie komputerów na całym świecie. Nie sądzę, aby ktokolwiek wdrożył pełny standard Fortran 2008 w odniesieniu do współ-macierzy, ale w kilku kompilatorach jest więcej niż tylko wsparcie. Cilk + jest oczywiście dostępny również z kompilatorami Intela, ale bycie zależnym prawdopodobnie nie jest jeszcze mądre.
Bill Barth

Standard Fortran 2008 nie został zatwierdzony do końca 2010 roku, więc minie kilka lat, zanim CAF będzie powszechnie dostępny. G95 faktycznie miał (niewolną) implementację, ale nie jest już rozwijany (programista dołączył do PathScale).
stali

Większość g95 ostatecznie trafiła do gfortranu, ale być może CAF nie jest tego częścią.
Wolfgang Bangerth

Wierzę, że kompilator Intel zapewnia dobre wsparcie dla macierzy. Zbudowali go za pomocą mpiexec. To nie będzie mój pierwszy wybór. Zaletą jest to, że ta sama implementacja może działać na pamięci współużytkowanej i rozproszonej (przeprowadziłem kilka testów). Ponieważ procesory pamięci wspólnej Opteron osiągają 60 rdzeni w naprawdę rozsądnych cenach, najpierw chcę zobaczyć opcje pamięci wspólnej.
electrique

2

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 .


Spojrzę na sugerowane linki. Papier porównawczy jest bardzo ładny! Dzięki! Myślałem o pthreads, ale chcę, aby program był wieloplatformowy. Z tego co wiem pthreads mają problemy pod oknami (źle?).
electrique

@ p3tris: „p” w pthreads dotyczy POSIX, więc jest tak przenośny, jak to tylko możliwe. Istnieje kilka zgodnych implementacji systemu Windows, takich jakpthreads-win32 lub w ramach cygwinprojektu.
Pedro

Na podstawie stackoverflow.com/q/2797690/801468 widzę, że jest wiele rzeczy, które trzeba uporządkować, aby z niego skorzystać. Ponieważ nie jestem programistą, wolę trzymać się czegoś bardziej przetestowanego.
electrique

2

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:

  • Cray ma kompilator, który obsługuje co najmniej podstawowe funkcje macierzy. Użyłem go do pisania kodu, który miał być „edukacyjny”, ale powiedziałbym, że można napisać prawdziwy kod w coarray fortran. Składnia i pojęcia są w większości znacznie prostsze niż MPI, ale jak zawsze są pułapki lotsa, a pułapki różnią się od MPI.
  • Intel fortran ma wbudowaną obsługę coarray w swojej bibliotece MPI. Podobno ogranicza to ich teoretyczną szczytową wydajność, ale nie widziałem żadnych danych.
  • Gfortran obsługuje prostokąty, ale tylko dla jednego obrazu (lub pojedynczej rangi, w mowie MPI). Dlatego nie jest dostępna żadna prawdziwa równoległość, dopóki nie pojawi się gfortran 4.8 lub 4.9.

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.


Tak, z pewnością pomocne byłyby dodatkowe informacje na temat gotowości prostaka Fortran na tego rodzaju problem. Witamy w scicomp!
Aron Ahmadia

1

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):

//load data to distributed memory
val points = spark.textFile(...).map(parsePoint).cache()
var w = Vector.random(D) // current separating plane
for (i <- 1 to ITERATIONS) {
  val gradient = points.map(p =>
    (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
  ).reduce(_ + _)
  w -= gradient
}
println("Final separating plane: " + w)

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

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.