(jak) pisać symulacje, które działają szybciej?

16

Zacząłem używać Pythona jako języka programowania do wykonywania wszystkich moich zadań w CFD. Mam bardzo małe doświadczenie w programowaniu. Pochodzę z inżynierii mechanicznej i studiuję na kierunku inżynieria lotnicza.

czasami obliczeniowy aspekt CFD staje się bardziej nużący niż manipulowanie równaniami lub robienie matematyki.

Jakie są ogólne wytyczne, które przyspieszają uruchamianie naszego programu? Jakie są sztuczki, aby robić rzeczy równolegle? Jak pisać kody, które działają szybciej?

Gdzie znajdę zasoby (łatwe do zrozumienia dla laika takiego jak ja), które odpowiedzą na powyższe pytania?

Subodh
źródło
@ Dan, nie sądzę. Proszę o „każdy” możliwy zasób, który pomoże zrozumieć taktykę programowania dla początkujących. Nie mam narzuconych żadnych szczególnych wymagań ani warunków. Mówiąc dokładniej, proszę o zasoby, które pomogą uczynić kody bardziej eleganckimi.
Subodh
Czy jesteś naprawiony na Pythonie, czy może rozważasz C ++? W tym przypadku zasugerowałbym dwie rzeczy: naucz się C ++, znajdź bibliotekę open source (w moim przypadku OpenFOAM), nie rozwijaj rzeczy od zera, ale ucz się, przekopuj zaawansowany fragment kodu, dowiedz się o jego aspekcie, zmianie i eksperymentuj, wszystkie prowadzone w określonym celu: w twoim przypadku, np. symulacje aerodynamiczne.
tmaric
@ tomislav-maric, bardzo dziękuję. Nie jestem ścisłym „pythonianem”. W rzeczywistości, będąc nowicjuszem w tej dziedzinie, myślę, że mam przed sobą mnóstwo opcji. Uczę się też OpenFOAM. Zgadzam się zatem z twoimi poglądami, że należy rozpocząć pracę nad projektem i nauczyć się przez to (lub w skrócie zabrudzić ręce), i właśnie to powinienem zrobić! Dzięki.
Subodh
@smj btw, pochodzę również z inżynierii mechanicznej i jestem teraz absolwentem informatyki (inżynieria mechaniczna NIE przygotowała mnie do tego) ... Jeśli pracujesz z OF, poszukaj książki C ++ listę przepełnienia stosu i rozpocznij naukę. Potrzebujesz 3 rzeczy: C ++, OpenFOAM i wiedzy z zakresu informatyki. OpenFOAM i nauki obliczeniowe, możesz uczyć się w dendrytyczny sposób: znajdź zadanie i zrób to, ucząc się tego, czego potrzebujesz. Posiadanie czegoś gotowego zmotywuje cię. Co do C ++: zacznij od C ++ Primer i naucz się go. Powodzenia! :)
tmaric

Odpowiedzi:

19

Spróbuję odpowiedzieć na twoje pytanie, biorąc pod uwagę, że pytasz konkretnie o Pythona. Opiszę własną metodę rozwiązania problemu symulacji. W tym opisie podano strategie szybszych symulacji.

Najpierw prototypuję nowe symulacje w Pythonie. Oczywiście staram się korzystać z NumPy i SciPy w miarę możliwości. Podczas gdy NumPy zapewnia odpowiedni typ danych tablicowych do symulacji numerycznych, SciPy oferuje szerokie procedury numeryczne działające z tablicami NumPy.

Gdy prototypy zaczną działać mniej więcej, próbuję dowiedzieć się, które części programu lub skryptu stanowią wąskie gardło. Są na to typowi kandydaci:

  • Pętle w Pythonie są wolne. Bardzo wolno.
  • Ponieważ Python używa pisania kaczego , funkcje wywoływania mogą być wolne.

Używam prostej strategii profilowania, aby dowiedzieć się, gdzie spędzany jest cały czas działania. Używając powłoki IPython (której nie mogę wystarczająco polecić), uruchamiam skrypt

%timeit script.py

To „magiczne polecenie” wykona dla ciebie profilowanie (używając timeit ) i wyświetli listę czasów, kiedy skrypt się zakończy. Skorzystaj z tej listy, aby dowiedzieć się, gdzie twój kod jest zbyt wolny.

Po przybiciu części, które należy przyspieszyć, możesz rozważyć użycie skompilowanych języków. Wskażę dwa rozwiązania.

Po pierwsze, istnieje język Cython . Cython jest językiem programowania bardzo podobnym do Pythona (w rzeczywistości kod Pythona jest często również prawidłowym kodem Pythona); jednak kompilator Cython konwertuje pliki Cython na kod C, który następnie można skompilować w moduł używany z Pythona. Cython rozumie tablice NumPy. Są dwa sposoby, w których użycie Cython może ci pomóc: po pierwsze, możesz wprowadzić typy danych. Przyspieszy to wywołania funkcji. Ponadto, jeśli wykonasz iterację po tablicach, twoja pętla będzie działać szybciej (w rzeczywistości, jeśli wpiszesz zarówno zmienną fikcyjną, jak i tablicę, otrzymasz zwykłą pętlę C!). Po drugie, w moich eksperymentach nawet nieskryptowane skrypty działają nieco szybciej, ponieważ są one kompilowane zamiast interpretowane.

Innym skompilowanym językiem, który będzie ci przydatny, jest Fortran. Istnieją różne sposoby korzystania z Fortran z Pythonem ( f2py , fortwrap , Cython ). Jeśli chodzi o mnie osobiście, f2py wydaje się najłatwiejszym sposobem, szybko opiszę, co robi. f2py może kompilować kod Fortran do modułów Pythona. Umożliwi to użycie tablic NumPy jako zmiennych wejściowych i wyjściowych z przestrzeni Pythona. W przestrzeni Fortran będą to zwykłe tablice Fortrana. Możesz operować nimi przy pełnej prędkości Fortrana.

Osobiście zwykle używam Cython, gdzie liczba wywołań funkcji jest wąskim gardłem. W przypadku rzeczy z dużą ilością pętli wolę f2py (może dlatego, że mam silne tło Fortran).

Na dodatkowe uwagi na temat Fortran: nowoczesny Fortran czyta i pisze bardzo podobnie do NumPy - składnia jest bardzo bliska. Ułatwia to konwersję kodu NumPy na kod Fortran.

Zauważ, że zarówno Cython, jak i f2py w jakiś sposób wspierają paraliżizm. W przypadku Cython znajdziesz tutaj pomoc , natomiast w przypadku Fortran istnieją standardowe techniki, takie jak OpenMP lub MPI. Ponadto istnieją również opakowania Pthon dla MPI . Osobiście używam mpi4py na poziomie Python, a także OpenMP w Fortran.

Pozwól mi polecić trochę literatury: książkę Python Scripting For Computational Science autorstwa H.-P. Langtangen jest świetnym źródłem informacji o Pythonie, a także o strategiach, dzięki którym Python jest nieco szybszy. Niestety, AFAIR, nie wspomina nic o Cython. Jako drugi zasób możesz obejrzeć te slajdy . Dają one przykłady wszystkiego, o czym wspomniałem w tym poście (zobacz także kod i źródła tutaj ). Istnieje wiele innych dobrych zestawów slajdów w Internecie.

Jeśli masz bardziej szczegółowe pytania, wszyscy chętnie Ci pomożemy!

AlexE
źródło
7

W przypadku CFD + Python istnieje rozwiązanie: http://pythonflu.wikidot.com/ Są to wiązania Pythona na platformie OpenFOAM (o której już wspomniano w komentarzach do pytań). Wiązania te umożliwiają programowanie na „poziomie solvera” (istnieją przykłady, w których oryginalne solwery OpenFOAM są replikowane w Pythonie i nie są wolniejsze niż oryginały - powolne pętle wspomniane w innej odpowiedzi nie są tutaj problemem, ponieważ zdarzają się „pętle wewnętrzne” w kodzie C ++ OpenFOAM).

Zaletą tych powiązań jest również to, że cała równoległość w OpenFOAM odbywa się poniżej poziomu solvera, więc nie musisz się tym przejmować (a także innych rzeczy, którymi zajmuje się rdzeń OpenFOAM: wejście / wyjście, solver liniowy, dyskretyzacja operatora)

Więc jeśli chcesz po prostu napisać nowy solver i nie dodawać nowych funkcji do rdzenia OF (warunki brzegowe, solver liniowy itp.), To PythonFlu może być dla Ciebie wystarczający i możesz uniknąć C ++ (który ma znacznie lepsze lekcje uczenia się niż Pyton)

PS: pierwotnie chciałem dodać to jako komentarz do dyskusji na temat pierwotnego pytania, ale moja reputacja na to nie pozwala

bgschaid
źródło
Cześć Bernhard! Witamy w scicomp! :)
tmaric