Najpierw szukałem informacji i nie mogłem znaleźć odpowiedzi na moje pytanie. Próbuję uruchomić wiele funkcji równolegle w Pythonie.
Mam coś takiego:
files.py
import common #common is a util class that handles all the IO stuff
dir1 = 'C:\folder1'
dir2 = 'C:\folder2'
filename = 'test.txt'
addFiles = [25, 5, 15, 35, 45, 25, 5, 15, 35, 45]
def func1():
c = common.Common()
for i in range(len(addFiles)):
c.createFiles(addFiles[i], filename, dir1)
c.getFiles(dir1)
time.sleep(10)
c.removeFiles(addFiles[i], dir1)
c.getFiles(dir1)
def func2():
c = common.Common()
for i in range(len(addFiles)):
c.createFiles(addFiles[i], filename, dir2)
c.getFiles(dir2)
time.sleep(10)
c.removeFiles(addFiles[i], dir2)
c.getFiles(dir2)
Chcę wywołać func1 i func2 i uruchomić je w tym samym czasie. Funkcje nie oddziałują na siebie ani na ten sam obiekt. W tej chwili muszę poczekać na zakończenie funkcji func1 przed uruchomieniem funkcji func2. Jak mogę zrobić coś takiego jak poniżej:
process.py
from files import func1, func2
runBothFunc(func1(), func2())
Chcę mieć możliwość tworzenia obu katalogów w przybliżeniu w tym samym czasie, ponieważ co minutę liczę, ile plików jest tworzonych. Jeśli katalogu tam nie ma, wpłynie to na mój czas.
Odpowiedzi:
Możesz użyć
threading
lubmultiprocessing
.Ze względu na specyfikę CPython ,
threading
jest mało prawdopodobne, aby osiągnąć prawdziwą równoległość. Z tego powodumultiprocessing
jest ogólnie lepszym zakładem.Oto pełny przykład:
Mechanizm uruchamiania / dołączania procesów potomnych można łatwo zamknąć w funkcji zgodnie z
runBothFunc
:źródło
Można to zrobić elegancko za pomocą Ray , systemu, który umożliwia łatwe zrównoleglenie i dystrybucję kodu Pythona.
Aby zrównoleglać swój przykład, musisz zdefiniować swoje funkcje za pomocą
@ray.remote
dekoratora, a następnie wywołać je za pomocą.remote
.Jeśli przekażesz ten sam argument do obu funkcji, a argument jest duży, wydajniejszym sposobem jest użycie
ray.put()
. Pozwala to uniknąć podwójnego serializacji dużego argumentu i utworzyć dwie kopie pamięci:Jeśli
func1()
ifunc2()
zwrócisz wyniki, musisz przepisać kod w następujący sposób:Stosowanie Ray w porównaniu z modułem wieloprocesorowym ma wiele zalet . W szczególności ten sam kod będzie działał na pojedynczej maszynie, jak również na klastrze maszyn. Aby uzyskać więcej zalet Ray, zobacz ten powiązany post .
źródło
Jeśli twoje funkcje wykonują głównie operacje we / wy (i mniej pracy procesora) i masz Python 3.2+, możesz użyć ThreadPoolExecutor :
Jeśli twoje funkcje wykonują głównie pracę procesora (i mniej pracy we / wy) i masz Python 2.6+, możesz użyć modułu wieloprocesorowego :
źródło
Jeśli jesteś użytkownikiem systemu Windows i korzystasz z Pythona 3, ten post pomoże ci w programowaniu równoległym w pythonie. Po uruchomieniu zwykłego programowania puli biblioteki wieloprocesorowej, otrzymasz błąd dotyczący głównej funkcji w twoim programie. Wynika to z faktu, że okna nie mają funkcji fork (). Poniższy post przedstawia rozwiązanie wspomnianego problemu.
http://python.6.x6.nabble.com/Multiprocessing-Pool-woes-td5047050.html
Ponieważ używałem Pythona 3, zmieniłem program trochę w ten sposób:
Po tej funkcji powyższy kod problemu również zmienia się trochę w ten sposób:
Otrzymałem wynik jako:
Myślę, że ten post może być przydatny dla niektórych użytkowników systemu Windows.
źródło
Nie ma sposobu, aby zagwarantować, że dwie funkcje zostaną zsynchronizowane ze sobą, co wydaje się być tym, co chcesz zrobić.
Najlepsze, co możesz zrobić, to podzielić funkcję na kilka kroków, a następnie poczekać, aż oba zakończą się w krytycznych punktach synchronizacji, używając
Process.join
wzmianek w odpowiedzi jak @ aix.Jest to lepsze niż to,
time.sleep(10)
że nie możesz zagwarantować dokładnych czasów. Z jawnym czekaniem mówisz, że funkcje muszą zostać wykonane, wykonując ten krok przed przejściem do następnego, zamiast zakładać, że zostanie to wykonane w ciągu 10 ms, co nie jest gwarantowane na podstawie tego, co jeszcze dzieje się na komputerze.źródło
Wygląda na to, że masz jedną funkcję, którą musisz wywołać dla dwóch różnych parametrów. Można to elegancko zrobić używając kombinacji
concurrent.futures
imap
z Pythonem 3.2+Teraz, jeśli twoja operacja jest związana z IO, możesz użyć
ThreadPoolExecutor
jako takiego:Zwróć uwagę, w jaki sposób
map
została użytamap
Twoja funkcja do listy argumentów.Teraz, jeśli twoja funkcja jest związana z procesorem, możesz użyć
ProcessPoolExecutor
Jeśli nie masz pewności, możesz po prostu wypróbować oba i sprawdzić, który z nich daje lepsze wyniki.
Wreszcie, jeśli chcesz wydrukować wyniki, możesz po prostu zrobić to:
źródło