Czy są jakieś narzędzia w Pythonie, które są podobne do parla Matlaba? Znalazłem ten wątek , ale ma on cztery lata. Myślałem, że może ktoś tutaj może mieć nowsze doświadczenia.
Oto przykład tego, co chciałbym zrównoważyć:
X = np.random.normal(size=(10, 3))
F = np.zeros((10, ))
for i in range(10):
F[i] = my_function(X[i,:])
gdzie my_function
przyjmuje ndarray
rozmiar (1,3)
i zwraca skalar.
Przynajmniej chciałbym używać wielu rdzeni jednocześnie --- jak parfor. Innymi słowy, załóżmy, że mamy do czynienia z systemem pamięci wspólnej z rdzeniami od 8 do 16.
python
parallel-computing
Paul G. Constantine
źródło
źródło
Odpowiedzi:
Joblib robi to, co chcesz. Podstawowy wzorzec użytkowania to:
gdzie
arg_instances
jest listą wartości, dla którychmyfun
jest obliczana równolegle. Głównym ograniczeniem jest to, żemyfun
musi to być funkcja najwyższego poziomu.backend
Parametr może być"threading"
albo"multiprocessing"
.Możesz przekazać dodatkowe wspólne parametry do funkcji równoległej. Treść
myfun
może również odnosić się do zainicjowanych zmiennych globalnych, wartości, które będą dostępne dla dzieci.Argumenty i wyniki mogą być praktycznie wszystkim z backendem wątków, ale wyniki muszą być możliwe do serializacji z backendem wieloprocesowym.
Dask oferuje również podobną funkcjonalność. Może być bardziej wskazane, jeśli pracujesz z danymi podstawowymi lub próbujesz zrównoleglić bardziej złożone obliczenia.
źródło
threading
backend cierpi z powodu wąskiego gardła GIL, amultiprocessing
backend wiąże się z dużym obciążeniem z powodu serializacji wszystkich parametrów i wartości zwracanych. Zobacz tę odpowiedź, aby poznać szczegóły niskiego poziomu przetwarzania równoległego w Pythonie.map
, z której można korzystać bezpośrednio. Również jeśli użyjesz numpy skompilowanej przez mkl, automatycznie zrównoleglą operacje wektoryzowane bez robienia czegokolwiek. Numpy w Ananconda ma domyślnie włączone mkl. Nie ma jednak uniwersalnego rozwiązania. Joblib ma bardzo małe zamieszanie i w 2015 roku było mniej okazji.To, czego szukasz, to Numba , która może automatycznie zrównoleglać pętlę for. Z ich dokumentacji
źródło
Bez zakładania czegoś specjalnego przy
my_function
wyborzemultiprocessing.Pool().map()
można zgadywać równolegle do tak prostych pętli.joblib
,dask
,mpi
Obliczenia lubnumba
jak zaproponowano w innych odpowiedzi wygląda nie przynosząc żadnych korzyści dla takich przypadków użycia i dodawać niepotrzebnych zależności (podsumować są przesadą). Używanie wątków, jak zaproponowano w innej odpowiedzi, raczej nie będzie dobrym rozwiązaniem, ponieważ musisz być blisko interakcji GIL z twoim kodem lub twój kod powinien wykonywać głównie operacje wejścia / wyjścia.To powiedziawszy
numba
może być dobrym pomysłem, aby przyspieszyć sekwencyjny czysty kod Pythona, ale czuję, że jest to poza zakresem pytania.Istnieją jednak pewne zastrzeżenia (które nie powinny mieć wpływu na większość aplikacji):
if __name__ == "__main__"
my_function
nie powinny zależeć od wspólnych stanów, takich jak komunikacja ze zmiennymi globalnymi, ponieważ stany nie są współużytkowane między procesami. funkcje czyste (funkcje w sensie matematycznym) są przykładem funkcji, które nie dzielą stanówźródło
Mam wrażenie, że parfor jest taki, że MATLAB hermetyzuje szczegóły implementacji, więc może on używać zarówno równoległości pamięci współużytkowanej (co jest potrzebne), jak i równoległości pamięci rozproszonej (jeśli korzystasz z rozproszonego serwera obliczeniowego MATLAB ).
Jeśli chcesz równoległości pamięci współużytkowanej i wykonujesz coś w rodzaju równoległej pętli zadań, prawdopodobnie potrzebujesz standardowego pakietu bibliotek wieloprocesorowych , może z ładnym front- endem , takim jak joblib , jak wspomniano w poście Douga. Standardowa biblioteka nie zniknie i jest utrzymywana, więc jest niskiego ryzyka.
Istnieją również inne opcje, takie jak równoległe możliwości Pythona i równoległe możliwości IPython . Szybki rzut oka na Parallel Python sprawia, że myślę, że jest bliżej ducha parfor, ponieważ biblioteka zawiera szczegółowe dane dla rozproszonej skrzynki, ale kosztem tego jest konieczność przyjęcia ich ekosystemu. Koszt korzystania z IPython jest podobny; musisz przyjąć sposób wykonywania rzeczy przez IPython, co może, ale nie musi być tego warte.
Jeśli zależy ci na pamięci rozproszonej, polecam mpi4py . Lisandro Dalcin wykonuje świetną robotę, a mpi4py jest używany w opakowaniach PETSc Python, więc nie sądzę, że wkrótce zniknie. Podobnie jak przetwarzanie wieloprocesowe, jest to interfejs o niskim (er) poziomie równoległości niż parfor, ale taki, który prawdopodobnie potrwa przez jakiś czas.
źródło
Zanim zacznę szukać narzędzia „czarnej skrzynki”, którego można używać do równoległego wykonywania „ogólnych” funkcji pytona, sugeruję przeanalizować, w jaki sposób
my_function()
można go sparaliżować ręcznie.Najpierw porównaj czas wykonania narzutu
my_function(v)
dofor
pętli Pythona : [C]for
Pętle Pythona są dość wolne, więc czas spędzony w nichmy_function()
może być znikomy.Drugie sprawdzenie, czy istnieje prosta implementacja wektorowa
my_function(v)
, która nie wymaga pętli:F[:] = my_vector_function(X)
(Te dwa pierwsze punkty są dość trywialne, wybacz mi, jeśli wspomniałem je tutaj tylko dla kompletności.)
Po trzecie i najważniejsze, przynajmniej dla wdrożeń CPython, jest sprawdzenie, czy
my_function
spędza większość nadszedł czas, wewnątrz lub na zewnątrz w Global Interpreter Lock lub GIL . Jeśli czas spędza się poza GIL, należy użyćthreading
standardowego modułu bibliotecznego . ( Oto przykład). BTW, można by pomyśleć o pisaniumy_function()
jako rozszerzenie C tylko po to, aby wydać GIL.Wreszcie, jeśli
my_function()
nie wyda GIL, można użyćmultiprocessing
modułu .Odnośniki: Dokumenty Pythona dotyczące jednoczesnego wykonywania i wprowadzenie numpy / scipy do przetwarzania równoległego .
źródło
Możesz spróbować Julii. Jest dość zbliżony do Pythona i ma wiele konstrukcji MATLAB. Tłumaczenie tutaj to:
To sprawia, że liczby losowe są również równoległe i po prostu łączą wyniki na końcu podczas redukcji. Korzysta z przetwarzania wieloprocesorowego (więc musisz
addprocs(N)
dodać procesy przed użyciem, i działa to również na wielu węzłach na HPC, jak pokazano w tym poście na blogu ).Zamiast tego możesz również użyć
pmap
:Jeśli chcesz równoległości wątków, możesz użyć
Threads.@threads
(ale upewnij się, że algorytm jest bezpieczny dla wątków). Przed otwarciem Julii ustaw zmienną środowiskową JULIA_NUM_THREADS, a następnie:Tutaj tworzę osobną tablicę dla każdego wątku, aby w ten sposób nie kolidowały podczas dodawania do tablicy, a następnie po prostu łączyły tablice. Wątek jest całkiem nowy, więc teraz jest proste użycie wątków, ale jestem pewien, że zostaną dodane redukcje wątków i mapy, tak jak w przypadku przetwarzania wieloprocesowego.
źródło
Polecam korzystać z biblioteki równoległej i opóźnionej funkcji Joblib. Użyj modułu „tempfile” do tworzenia tymczasowej pamięci współużytkowanej dla dużych tablic, przykłady i użycie można znaleźć tutaj https://pythonhosted.org/joblib/parallel.html
źródło