Sembra che il tuo codice è di I/O bound. Ciò significa che il multiprocessing non ti aiuterà: se passi il 90% del tuo tempo a leggere dal disco, avere 7 processi extra in attesa della prossima lettura non aiuterà nulla.
E, mentre si utilizza un modulo di lettura CSV (se del stdlib csv
o qualcosa di simile NumPy o Pandas) può essere una buona idea per semplicità, è improbabile fare molta differenza in termini di prestazioni.
Ancora, vale la pena controllare che davvero sono vincolato I/O, invece di solo indovinare. Esegui il tuo programma e verifica se l'utilizzo della CPU è vicino allo 0% o vicino al 100% o un core. Fai quello che Amadan ha suggerito in un commento ed esegui il tuo programma con il solo pass
per l'elaborazione e verifica se questo taglia il 5% delle volte o il 70%. Potresti anche provare a confrontare un ciclo su os.open
e os.read(1024*1024)
o qualcosa del genere e vedere se è più veloce.
Dal momento che la vostra utilizzando Python 2.x, Python è affidamento sulla libreria stdio C a indovinare quanto a tampone in un momento, quindi potrebbe essere la pena costringendolo a tamponare di più. Il modo più semplice per farlo è utilizzare readlines(bufsize)
per alcuni grandi bufsize
. (Puoi provare numeri diversi e misurarli per vedere dove è il picco. Nella mia esperienza, di solito qualsiasi cosa da 64K-8MB è più o meno la stessa, ma dipende dal tuo sistema che potrebbe essere diverso, specialmente se stai leggendo ad esempio fuori un filesystem di rete con grande rendimento ma la latenza orribile che sommerge il throughput-vs-latenza del disco fisico reale e la memorizzazione nella cache del sistema operativo fa)
Così, per esempio:.
bufsize = 65536
with open(path) as infile:
while True:
lines = infile.readlines(bufsize)
if not lines:
break
for line in lines:
process(line)
Nel frattempo, supponendo che tu sia su un sistema a 64 bit, potresti provare a utilizzare mmap
invece di leggere il file in primo luogo. Questo certamente non è garantito per essere migliore, ma è maggio essere migliore, a seconda del sistema.Ad esempio:
with open(path) as infile:
m = mmap.mmap(infile, 0, access=mmap.ACCESS_READ)
un pitone mmap
è una sorta di strano oggetto agisce come un str
e come un file
allo stesso tempo, in modo da poter, ad esempio, manualmente scansione iterazione per newlines, oppure si può chiamare readline
su di esso come se fosse un file. Entrambi richiedono più elaborazione da Python che iterando il file come linee o facendo batch readlines
(perché un loop che sarebbe in C ora è in puro Python ... anche se forse è possibile aggirare il problema con re
, o con una semplice estensione Cython ?) ... ma il vantaggio I/O del sistema operativo sapendo che cosa stai facendo con la mappatura può invertire lo svantaggio della CPU.
Purtroppo, Python non espone la chiamata madvise
che usereste per modificare le cose, nel tentativo di ottimizzare questo in C (ad esempio, impostando esplicitamente MADV_SEQUENTIAL
invece di fare l'ipotesi del kernel, o forzare le pagine enormi trasparenti) - ma in realtà è possibile eseguire la funzione ctypes
da libc
.
multiprocessing; lettura iterativa chunked. A 3 GB per file, ** NON ** vuoi leggerlo interamente in memoria; puoi soffiare le tue risorse di memoria. –
Sembra che un database ti aiuti a seconda del tipo di elaborazione che stai facendo. – squiguy
Non se questa è un'attività a singolo lancio; dati-in; in lavorazione; uscita dati; cancella i dati di origine. –