Possiedo un'utilità che genera più worker utilizzando il modulo Python multiprocessing
e mi piacerebbe essere in grado di monitorare l'utilizzo della memoria tramite l'eccellente utility memory_profiler
, che fa tutto ciò che voglio, in particolare campionando l'utilizzo della memoria nel tempo e tracciando il risultato finale (non mi interessa il profilo di memoria riga per riga per questa domanda).Come profilare più sottoprocessi usando Python multiprocessing e memory_profiler?
Per impostare questa domanda, ho creato una versione più semplice dello script, che ha una funzione di lavoro che alloca memoria simile a example dato nella libreria memory_profiler
. Il lavoratore è la seguente:
import time
X6 = 10 ** 6
X7 = 10 ** 7
def worker(num, wait, amt=X6):
"""
A function that allocates memory over time.
"""
frame = []
for idx in range(num):
frame.extend([1] * amt)
time.sleep(wait)
del frame
dato un carico di lavoro sequenziale di 4 lavoratori come segue:
if __name__ == '__main__':
worker(5, 5, X6)
worker(5, 2, X7)
worker(5, 5, X6)
worker(5, 2, X7)
Esecuzione dei mprof
eseguibile per il profilo my script prende 70 secondi con ogni esecuzione lavoratore uno dopo l'altro. Lo script, eseguito come segue:
$ mprof run python myscript.py
produce il seguente grafico di utilizzo della memoria:
Avendo questi lavoratori vanno in parallelo con multiprocessing
significa che lo script si concluderà lento come il lavoratore più lento (25 secondi). Questo script è il seguente:
import multiprocessing as mp
if __name__ == '__main__':
pool = mp.Pool(processes=4)
tasks = [
pool.apply_async(worker, args) for args in
[(5, 5, X6), (5, 2, X7), (5, 5, X6), (5, 2, X7)]
]
results = [p.get() for p in tasks]
profiler di memoria effettivamente funziona, o almeno non ci sono errori quando si utilizza mprof
ma i risultati sono un po 'strano:
Un rapido sguardo a Activity Monitor mostra che in effetti ci sono 6 processi Python, uno per mprof
uno per python myscript.py
e uno per ciascun sottoprocesso di lavoro. Sembra che mprof
stia misurando solo l'utilizzo della memoria per il processo python myscript.py
.
La biblioteca memory_profiler
è altamente personalizzabile, e sono abbastanza sicuro che dovrei essere in grado di catturare la memoria di ogni processo ed eventualmente scrivere per separare i file di log utilizzando la libreria stessa. Non sono sicuro di dove cominciare o come avvicinarmi a quel livello di personalizzazione.
EDIT
Dopo aver letto il copione mprof
ho fatto scoprire la bandiera -C
che riassume l'utilizzo della memoria di tutti i bambini (a forcella) processi. Questo porta ad un (molto migliorato) grafico come segue:
Ma quello che sto cercando è l'utilizzo della memoria di ogni singolo sottoprocesso nel tempo in modo che io possa tracciare tutti i lavoratori (e il master) sullo stesso grafico. La mia idea è di avere ogni sottoprocesso memory_usage
scritto in un file di registro diverso, che posso quindi visualizzare.
Questa domanda è in discussione con gli sviluppatori su GitHub all'indirizzo https://github.com/fabianp/memory_profiler/issues/118 se qualcuno è interessato. – bbengfort