Migliori pratiche di Torch.multiprocessing

Tuttavia, la memoria virtuale è solo un lato della storia. Cosa succede se il problema persiste dopo aver regolato il disco di scambio?

L'altro lato della storia riguarda i problemi di fondo del modulo torch.multiprocessing. Sulla pagina web ufficiale sono presenti numerosi consigli sulle migliori pratiche:

Ma oltre a questi, dovrebbero essere considerati altri tre approcci, soprattutto per quanto riguarda l’utilizzo della memoria.

La prima cosa è la perdita di memoria condivisa. Perdita significa che la memoria non viene rilasciata correttamente dopo ogni esecuzione del lavoratore figlio e osserverai questo fenomeno quando monitorerai l'utilizzo della memoria virtuale in fase di runtime. Il consumo di memoria continuerà ad aumentare e raggiungerà il punto di essere “senza memoria”. Questa è una tipica perdita di memoria.

Quindi cosa causerà la perdita?

Diamo un'occhiata alla classe DataLoader stessa:

https://github.com/pytorch/pytorch/blob/main/torch/utils/data/dataloader.py

Guardando sotto il cofano di DataLoader, vedremo che quando nums_worker > 0, viene chiamato _MultiProcessingDataLoaderIter. All'interno di _MultiProcessingDataLoaderIter, Torch.multiprocessing crea la coda di lavoro. Torch.multiprocessing utilizza due diverse strategie per la condivisione della memoria e il caching: descrittore_file E file_system. Mentre file_system non richiede la memorizzazione nella cache dei descrittori di file, è soggetto a perdite di memoria condivisa.

Per verificare quale strategia di condivisione sta utilizzando la tua macchina, aggiungi semplicemente lo script:

torch.multiprocessing.get_sharing_strategy()

Per ottenere il limite del descrittore di file di sistema (Linux), esegui il seguente comando nel terminale:

ulimit -n

Per cambiare la tua strategia di condivisione in descrittore_file:

torch.multiprocessing.set_sharing_strategy(‘file_descriptor’)

Per contare il numero di descrittori di file aperti, eseguire il comando seguente:

ls /proc/self/fd | wc -l

Finché il sistema lo consente, il descrittore_file si consiglia una strategia

Il secondo è il metodo di avvio del lavoratore multiprocessore. In parole povere, si tratta del dibattito se utilizzare un fork o lo spawn come metodo di partenza del lavoratore. Il fork è il modo predefinito per avviare il multiprocessing in Linux e può evitare la copia di alcuni file, quindi è molto più veloce, ma potrebbe avere problemi nella gestione dei tensori CUDA e delle librerie di terze parti come OpenCV nel tuo DataLoader.

Per utilizzare il metodo spawn, puoi semplicemente passare l'argomento multiprocessing_context= “spawn”.. al DataLoader.

Tre: rendere selezionabili/serializzabili gli oggetti del set di dati

C'è un post molto carino che discute ulteriormente dell'effetto “copia su lettura” per la piegatura del processo: https://ppwwyyxx.com/blog/2022/Demystify-RAM-Usage-in-Multiprocess-DataLoader/

In poche parole, lo è non è più un buon approccio per creare un elenco di nomi di file e caricarli nel metodo __getitem__. Crea un array Numpy o un dataframe panda per archiviare l'elenco dei nomi di file a scopo di serializzazione. E se hai familiarità con HuggingFace, utilizzare un CSV/dataframe è il modo consigliato per caricare un set di dati locale: https://huggingface.co/docs/datasets/v2.19.0/en/package_reference/loading_methods#datasets.load_dataset.example-2

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *