Ecco il programma:Utilizzo della memoria continuano a crescere con multiprocessing.pool di Python
#!/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()
Ho trovato l'utilizzo della memoria (sia VIRT e RES) ha continuato a crescere fino ad close()/join(), c'è qualche soluzione per sbarazzarsi di questo? Ho provato maxtasksperchild con 2.7 ma non è stato d'aiuto neanche.
Ho un programma più complicato che chiama apply_async() ~ 6M volte, e al punto ~ 1.5M ho già ottenuto 6G + RES, per evitare tutti gli altri fattori, ho semplificato il programma alla versione precedente.
EDIT:
Si è rivelato questa versione funziona meglio, grazie per l'input di tutti:
#!/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()
non ho messo alcuna serratura lì come credo processo principale è a thread singolo (callback è più o meno come una cosa guidata dagli eventi per i documenti che ho letto).
Ho modificato il range dell'indice di v1 su 1.000.000, come su v2 e ho eseguito alcuni test: è strano per me v2 addirittura ~ 10% più veloce di v1 (33s vs 37s), forse v1 stava facendo troppi lavori di manutenzione interni. v2 è sicuramente un vincitore sull'utilizzo della memoria, non ha mai superato i 300M (VIRT) e 50M (RES), mentre la v1 era 370M/120M, la migliore era 330M/85M. Tutti i numeri erano solo 3 ~ 4 volte il test, solo come riferimento.
Solo speculare qui, ma mettere in coda un milione di oggetti occupa spazio. Forse renderli utili aiuterà. I documenti non sono definitivi, ma l'[esempio] (http://pydoc.net/Python/multiprocessing/2.6.2.1/multiprocessing.examples.mp_pool/) (cerca il callback di Test) mostra il risultato apply_async in attesa, anche quando ci sono callback. L'attesa potrebbe essere necessaria per cancellare una coda di risultati. – tdelaney
Quindi multiprocessing.pool potrebbe non essere lo strumento giusto per me, dato che il callback in realtà non fa i lavori di pulizia, è possibile effettuare la pulizia in callback? Il problema è che non posso aspettare dopo la chiamata apply_async() come in real world worker() richiede ~ 0,1 secondi per richiesta (diverse richieste HTTP). –
Wild guess: 'apply_asynch' crea una istanza [' AsynchResult'] (http://docs.python.org/2/library/multiprocessing.html#multiprocessing.pool.AsyncResult). Il 'Pool' probabilmente ha qualche riferimento a questi oggetti, dal momento che devono essere in grado di restituire il risultato quando il calcolo è terminato, ma nel tuo ciclo li stai semplicemente buttando via. Probabilmente dovresti chiamare 'get()' o 'wait()' sui risultati asynch ad un certo punto, magari usando l'argomento 'callback' di' apply_asynch'. – Bakuriu