Scrivendo blocchi di dati durante l'elaborazione - c'è un valore di convergenza a causa di vincoli hardware?

StackOverflow https://stackoverflow.com/questions/1989977

  •  22-09-2019
  •  | 
  •  

Domanda

Sono l'elaborazione dei dati da un disco rigido da un file di grandi dimensioni (elaborazione è veloce e non un sacco di spese generali) e poi a scrivere i risultati indietro (centinaia di migliaia di file).

ho iniziato a scrivere i risultati immediatamente in file, uno alla volta, che era l'opzione più lenta. Ho pensato che diventa molto più veloce se io costruisco un vettore di una certa quantità di file e poi scrivo tutti in una volta, per poi tornare al trattamento mentre l'hard disk è occupato per iscritto tutta quella roba che ho versato in esso (che almeno sembra essere quello che succede).

La mia domanda è, posso in qualche modo stimare un valore di convergenza per la quantità di dati che dovrei scrivere dai vincoli hardware? A me sembra essere un disco cosa buffer del disco, ho buffer di 16MB su quel disco rigido e ottenere questi valori (tutti per ~ 100000 file):

Buffer size      time (minutes)
------------------------------
no Buffer        ~ 8:30
 1 MB            ~ 6:15
10 MB            ~ 5:45
50 MB            ~ 7:00

O è solo una coincidenza?

Vorrei anche essere interessato a un'esperienza / regole pratiche su come scrivere le prestazioni deve essere ottimizzato in generale, ad esempio, sono più grandi blocchi di disco rigido disponibile, ecc.

Modifica

L'hardware è un'unità consumatore piuttosto standard (io sono uno studente, non un centro dati) WD 3,5 1TB / 7200 / 16MB / USB2, HFS + girevolmente, sistema operativo è MacOS 10.5. Sarò presto fare un tentativo su Ext3 / Linux e disco interno piuttosto che esterno).

È stato utile?

Soluzione

  

Posso in qualche modo stimare un valore di convergenza per la quantità di dati che dovrei scrivere dai vincoli hardware?

Non a lungo termine. Il problema è che le prestazioni in scrittura sta andando a dipendere pesantemente su almeno quattro cose:

  • Quali filesystem stai usando

  • Che algoritmo di scheduling del disco il kernel sta usando

  • Le caratteristiche hardware del disco

  • L'interconnessione hardware che si sta utilizzando

Per esempio, USB è più lento di IDE, che è più lento di SATA. Non mi sorprenderebbe se XFS erano molto più veloce di ext2 per la scrittura di molti file di piccole dimensioni. E kernel cambiare tutto il tempo. Quindi ci sono troppi fattori qui per rendere semplici previsioni facile.

Se fossi in te prenderei questi due passaggi:

  • Dividi il mio programma in più thread (o anche processi) e utilizzare un thread per fornire chiamate di sistema open, write, e close al sistema operativo il più rapidamente possibile. I punti di bonus se si può fare il numero di thread un parametro in fase di esecuzione.

  • Invece di cercare di valutare le prestazioni di caratteristiche hardware, scrivere un programma che cerca un po 'di alternative e trova il più veloce per la particolare combinazione di hardware e software in quel giorno. Salvare l'alternativa più veloce in un file o anche compilarlo in codice. Questa strategia è stata introdotta da Matteo Frigo per FFTW ed è notevolmente efficace.

Poi, quando si cambia il disco, la vostra interconnessione, il kernel, o il vostro CPU, si può semplicemente eseguire nuovamente il programma di configurazione e presto! Il vostro codice verrà ottimizzato per le migliori prestazioni.

Altri suggerimenti

La cosa importante è quello di ottenere il maggior numero di operazioni di scrittura in essere possibile, in modo che il sistema operativo in grado di ottimizzare l'accesso al disco rigido. Ciò significa utilizzare async I / O, o utilizzando un pool compito di scrivere in realtà i nuovi file su disco.

Detto questo, si dovrebbe guardare a ottimizzare il vostro accesso in lettura. Sistemi operativi (almeno Windows) è già veramente bravo ad aiutare l'accesso in scrittura tramite buffering "sotto il cofano", ma se la vostra lettura in serie non c'è troppo che possiamo fare per aiutare. Se l'uso async I / O o (di nuovo) un pool compito di elaborare / leggere più parti del file in una sola volta, probabilmente vedrete un aumento perf.

Analizzare XML dovrebbe essere fattibile a velocità praticamente disco in lettura, decine di MB / s. L'implementazione SAX non potrebbe fare questo.

Si potrebbe desiderare di utilizzare alcuni trucchi sporchi. 100.000s di file da scrivere non sta per essere efficiente con l'API normale.

Prova questo scrivendo in sequenza ad un singolo file prima, non 100.000. Confrontare le prestazioni. Se la differenza è interessante, a leggere.

Se davvero a capire il sistema di file che si sta scrivendo, è possibile assicurarsi che si sta scrivendo un blocco contiguo basta successivamente suddiviso in più file nella struttura di directory.

Si vuole blocchi più piccoli, in questo caso, non quelli più grandi, come i file stanno per essere piccolo. Tutto lo spazio libero in un blocco sta per essere azzerato.

[modifica] Hai davvero bisogno di un esterno per quei file 100K? Un singolo file con un indice potrebbe essere sufficiente.

Ampliando la risposta di Norman:. Se i file sono tutti andando in un unico file system, utilizzare un solo thread di supporto

La comunicazione tra il filo lettura e scrittura helper (s) è costituito da un doppio std::vector doppio tampone per helper. (Un tampone di proprietà del processo di scrittura e uno per il processo di lettura.) Il filo di lettura riempie il buffer finché un limite specificato allora blocchi. I tempi di filo di scrittura la velocità di scrittura con gettimeofday o qualsiasi altra cosa, e regola il limite. Se la scrittura è andato più veloce rispetto l'ultima volta, aumentare il buffer di X%. Se è andato più lento, regolare da -X%. X può essere di piccole dimensioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top