Oto program:Użycie pamięci ciągle rośnie z multiprocessing.pool Pythona
#!/usr/bin/python
import multiprocessing
def dummy_func(r):
pass
def worker():
pass
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=16)
for index in range(0,100000):
pool.apply_async(worker, callback=dummy_func)
# clean up
pool.close()
pool.join()
znalazłem wykorzystanie pamięci (zarówno VIRT i RES) rósł aż do końca()/join(), to istnieje rozwiązanie pozbyć się tego? Próbowałem maxtasksperchild z 2.7, ale to też nie pomogło.
Mam bardziej skomplikowany program, który wywołuje apply_async() ~ 6M razy, a przy ~ 1,5M punkcie Mam już 6G + OZE, aby uniknąć wszystkich innych czynników, uprościłem program do powyższej wersji.
EDIT:
Okazało się ta wersja działa lepiej, dzięki za wkład każdego z nas:
#!/usr/bin/python
import multiprocessing
ready_list = []
def dummy_func(index):
global ready_list
ready_list.append(index)
def worker(index):
return index
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=16)
result = {}
for index in range(0,1000000):
result[index] = (pool.apply_async(worker, (index,), callback=dummy_func))
for ready in ready_list:
result[ready].wait()
del result[ready]
ready_list = []
# clean up
pool.close()
pool.join()
nie umieszczać żadnych blokadę tam wierzę główny proces jest pojedynczy gwintowany (zwrotna jest mniej więcej tak, jak rzeczy sterowane zdarzeniami na dokumenty, które czytam).
Zmieniłem zakres indeksu v1 na 1 000 000, tak samo jak v2 i zrobiłem kilka testów - dla mnie to dziwne v2 jest nawet o 10% szybsze niż v1 (33s vs 37s), może v1 wykonywał zbyt wiele wewnętrznych zadań konserwacyjnych list. v2 jest zdecydowanie zwycięzcą pod względem wykorzystania pamięci, nigdy nie przekroczyło 300M (VIRT) i 50M (RES), podczas gdy v1 było 370M/120M, najlepsze było 330M/85M. Wszystkie liczby były tylko 3 ~ 4 razy testowanie, tylko odniesienia.
Wystarczy spekulować, ale kolejkowanie miliona obiektów zajmuje miejsce. Być może pomoże im grupowanie. Dokumenty nie są definitywne, ale [przykład] (http://pydoc.net/Python/multiprocessing/2.6.2.1/multiprocessing.examples.mp_pool/) (szukaj Testowania wywołania zwrotnego) pokazuje, że wynik testu jest oczekiwany, nawet gdy są wywołania zwrotne. Oczekiwanie może być konieczne, aby usunąć kolejkę wyników. – tdelaney
Tak więc multiprocessing.pool może nie być odpowiednim narzędziem dla mnie, ponieważ wywołanie zwrotne w rzeczywistości nie wykonuje zadań czyszczenia, czy można wykonać czyszczenie w wywołaniu zwrotnym? Problem polega na tym, że nie mogę czekać po wywołaniu apply_async(), ponieważ w rzeczywistym świecie robot() zajmuje ~ 0,1 sekundy na żądanie (kilka żądań HTTP). –
Wild guess: 'apply_asynch' tworzy instancję [' AsynchResult'] (http://docs.python.org/2/library/multiprocessing.html#multiprocessing.pool.AsyncResult). "Pula" prawdopodobnie ma pewne odniesienie do tych obiektów, ponieważ muszą one być w stanie zwrócić wynik po zakończeniu obliczeń, ale w swojej pętli po prostu je wyrzucasz. Prawdopodobnie powinieneś nazwać 'get()' lub 'wait()' na wynikach asynch w pewnym momencie, może używając argumentu 'callback'' apply_asynch'. – Bakuriu