Prowadzę wiele "zawstydzająco równoległych" projektów, które chciałabym zrównoważyć z modułem multiprocessing
. Jednak często wymagają one czytania dużych plików (większych niż 2 GB), przetwarzania ich wiersz po wierszu, wykonywania podstawowych obliczeń, a następnie zapisywania wyników. Jaki jest najlepszy sposób na podzielenie pliku i przetworzenie go za pomocą modułu wieloprocesorowego Pythona? Czy należy używać Queue
lub JoinableQueue
w multiprocessing
? A może sam moduł Queue
? Lub, czy powinienem mapować plik iterowalny nad pulą procesów przy użyciu multiprocessing
? Eksperymentowałem z tymi podejściami, ale koszty ogólne są ogromne w dystrybucji danych po linii. Oparłem się na lekkim projekcie filtrów rurowych, używając cat file | process1 --out-file out1 --num-processes 2 | process2 --out-file out2
, który przekazuje pewien procent danych wejściowych pierwszego procesu bezpośrednio do drugiego wejścia (patrz this post), ale chciałbym mieć rozwiązanie zawarte w całości w Pythonie.Jaki jest najlepszy sposób na dzielenie dużych plików w Pythonie na potrzeby wieloprocesowości?
Co zaskakujące, dokumentacja w języku Python nie sugeruje kanonicznego sposobu wykonania tej czynności (pomimo obszernej sekcji dotyczącej wytycznych programowania w dokumentacji multiprocessing
).
Dzięki, Vince
Informacje dodatkowe: Czas przetwarzania jednej linii zmienia. Niektóre problemy są szybkie i ledwo nie są związane z I/O, niektóre są związane z CPU. Zależne od CPU, niezależne zadania uzyskają pozycję zrównoleglania, tak że nawet nieefektywne sposoby przypisywania danych do funkcji przetwarzania będą nadal korzystne pod względem czasu zegara ściennego.
Dobrym przykładem jest skrypt, który wyodrębnia pola z linii, sprawdza różne flagi bitowe i zapisuje linie z pewnymi flagami do nowego pliku w całkowicie nowym formacie. To wydaje się być problemem związanym z wejściem/wyjściem, ale kiedy uruchomiłem go z moją tanią, współbieżną wersją z rurkami, było to około 20% szybsze. Po uruchomieniu go z pulą i mapą lub kolejką w trybie multiprocessing
jest zawsze o ponad 100% wolniejszy.
To jest dla mnie wielki zarzut o niezbyt eleganckim języku skryptowym - proste obliczenia równoczesne to ból bez wątków . Oczywiście, możesz to zrobić, ale niektóre zadania są o wiele prostsze w przypadku modelu z wątkami i zamkami. –
Gwintowana wersja "równoległa" (chyba) nigdy nie będzie szybsza, z wyjątkiem faktu, że wątki są szybciej tworzone niż procesy.GIL jest ogromnym wąskim gardłem dla programów wielowątkowych związanych z procesorem. Ponadto nie ma żadnych zmiennych obiektów, które muszą być współdzielone między procesami/wątkami, więc wielowątkowość nie jest tak naprawdę potrzebna w przypadku przetwarzania wieloprocesowego. – Vince
@Jeśli tak, to wszystko zależy od dokładnej okoliczności. W twoim, może nigdy nie być. W innych może. Chodzi mi o to, że dla większości współbieżnych operacji, które musiałem wykonać (w C), rzadko istniało uzasadnienie dla używania dodatkowego, potrzebnego do prawidłowego IPC, gdy wątki i blokady dają o wiele prostszy model. W przypadku większych problemów, które wymagają skalowania na różnych komputerach, jest to inna historia. –