Progettazione, come utilizzare l'hardware (più thread e / o GPU) durante l'indicizzazione (tramite un database) di un set molto grande di file binari

4

problema

  1. Come posso progettare il mio parser di file per massimizzare l'hardware durante l'elaborazione (creando metadati per) un file di grandi dimensioni

(cioè come evitare di essere bloccato da IO e di esaurire la memoria)

preferibilmente vorrei dare all'utente una "priorità alta" (blocca il sistema a parte l'interfaccia utente di avanzamento) e un'opzione "Esegui in background" (consente all'utente di iniziare a utilizzare i dati che sono già stati indicizzati / caricati)

Ipotesi

  1. Presumibilmente non avrò problemi con più thread leggere lo stesso insieme di file?
  2. Il modo in cui lo vedo il più grande collo di bottiglia / sarà scrivere nel database. Presumibilmente dovrò bloccarlo / sbloccarlo e fare in modo che ogni thread accoda i dati per scrivere in batch?
  3. Poiché ogni thread avrà bisogno di proprie code di dati, non sono sicuro di come assicurarsi che la macchina non abbia esaurito la memoria
  4. Quando si elaborano i blocchi di dati, in pratica voglio ottenere cose come medie, minimi e massimi, ho presunto che non posso usare la GPU per elaborare blocchi di dati come questo? sente come se ci fossero troppi dati condivisi per utilizzare la GPU qui.

dettaglio:

Sto lavorando con insiemi di dati molto grandi, suddivisi su più file (ogni file di dati "completo" è di 1.5 gb e spesso ci sono molti di questi file (ne sto vedendo uno ora che ne ha 10)

I dati contengono effettivamente una serie di buffer a cui voglio accedere 1 o più alla volta.

| HeaderInfo-datablock | HeaderInfo-datablock | HeaderInfo-datablock | (Migliaia)

Voglio passare attraverso il file di dati, riempiendo un database con informazioni di indice (così posso accedere rapidamente a blocchi specifici in base alle informazioni nell'intestazione o al datablock stesso). Se posso, vorrei anche scambiare le informazioni con un'immagine di un grafico mentre lo faccio.

Hardware

Il computer su cui verrà eseguito è un PC workstation adatto, quindi sono disponibili RAM e potenza di elaborazione sufficienti:)

Sulla macchina con specifiche superiori ci sono 64GB di ram e un i7 che ha 12 core (hyperthreaded) quindi in teoria potrei farla franca con il caricamento dell'intero file in memoria e quindi l'elaborazione. Ma alcune delle macchine con le specifiche inferiori hanno meno RAM e i file che le persone producono stanno diventando più grandi ogni giorno, quindi non è lungimirante pensare di basarsi su quel piano.

Tecnologia

Sto usando C # quindi qualsiasi suggerimento sui modi migliori per giudicare le funzionalità hardware in C # (in fase di esecuzione) e massimizzarli quando si accede a un set di file di grandi dimensioni, sarebbe un grande vantaggio

    
posta chrispepper1989 03.03.2015 - 10:43
fonte

2 risposte

2

Il tuo collo principale sarà sempre IO a meno che tu non stia facendo calcoli intensi. La soluzione migliore per spremere la maggior parte delle prestazioni dalla macchina di destinazione per leggere tutti i file in serie (uno alla volta) ed elaborare ogni file contemporaneamente (più pipeline di calcolo). Dato che stai usando C #, ti suggerirei di esaminare l'uso della Libreria parallela Task per la tua pipeline di calcolo. L'utilità di pianificazione è maledettamente intelligente sull'utilizzo della CPU. Puoi fornirgli dei suggerimenti specificando che determinate attività saranno di lunga durata, richiedendo quindi il loro thread.

Progetta la tua pipeline di elaborazione in modo che "estrae" i dati e non avrai mai più quel file in memoria alla volta. Ciò significa che ogni funzione che sposta la pipeline in avanti deve avere un meccanismo per portare i dati dalla fase precedente. L'esempio più comune di questo tipo di meccanismo in C # è la coppia di IEnumerable<T> e IEnumerator<T> e come funzionano con LINQ. Puoi pensare alle istruzioni LINQ come a una serie di operazioni di pipeline che non funzionano fino a quando non vengono richieste da una funzione avida come ToArray() .

    
risposta data 03.03.2015 - 17:33
fonte
1

Dovresti lanciare il maggior numero possibile di lavori I / O e lasciare che il SO faccia il suo lavoro, utilizzare l'I / O asincrono per farlo o mmap (). Non dare per scontato che tu sappia come farlo meglio del sistema operativo, invece puoi dare un suggerimento. Ecco perché c'è una chiamata come madvise (), per far sapere al sistema operativo se hai bisogno che i dati vengano letti una volta o in sequenza, ecc. Sì, anche con i dischi magnetici si desidera utilizzare ogni mandrino e provare a saturare l'ampiezza di banda I / O .

L'unica cosa che non dovresti fare è usare più memoria di quella che hai. Il cestino si verifica quando il sistema operativo deve leggere qualcosa, scartarlo e leggerlo di nuovo. Non è come mantenere occupato il sistema, che è l'obiettivo di avere un buon SO (utilizzo elevato).

    
risposta data 04.03.2015 - 06:38
fonte

Leggi altre domande sui tag