2011-11-10 14 views
5

Ho il seguente codice:Perché questo ciclo Parallel.ForEach non migliora le prestazioni?

  if (!this.writeDataStore.Exists(mat)) 
      { 
       BlockingCollection<ImageFile> imageFiles = new BlockingCollection<ImageFile>(); 
       Parallel.ForEach(fileGrouping, fi => DecompressAndReadGzFile(fi, imageFiles)); 


       this.PushIntoDb(mat, imageFiles.ToList()); 
      } 

DecompressAndReadGzFile è un metodo statico nella stessa classe che questo metodo è contenuta nel Come per il nome del metodo che sto decompressione e la lettura di file GZ, molti di loro, vale a dire fino. a 1000, quindi il sovraccarico della parallelizzazione ne vale la pena per i benefici. Tuttavia, non vedo i benefici. Quando utilizzo il profiler delle prestazioni ANTS, vedo che funzionano esattamente nello stesso momento in cui non si verifica alcuna parallelizzazione. Controllo anche i core della CPU con Process Explorer e sembra che ci sia probabilmente del lavoro su due core, ma un core sembra fare la maggior parte del lavoro. Cosa non riesco a capire fino a ottenere Parallel.ForOgni a decomprimere e leggere i file in parallelo?

DOMANDA AGGIORNATA: Qual è il modo più veloce per leggere le informazioni da un elenco di file?

problema (semplificato):

  1. C'è una lunga lista di file .gz (1200).
  2. Ogni file ha una riga contenente "DATI:", la posizione e il numero di riga non sono statici e possono variare da file a file.
  3. Abbiamo bisogno di recuperare il primo numero dopo "DATA:" (solo per semplicità) e riporlo in un oggetto in memoria (ad esempio un elenco)

Nella domanda iniziale, stavo usando il parallelo Per ogni ciclo, ma non sembra che la CPU sia vincolata su più di un core.

+0

C'è qualche sincronizzazione eseguita in 'DecompressAndReadGzFile'? – SimonC

+0

Non che io sappia. Sebbene ci sia una chiamata a imageFiles.Add che aggiunge automaticamente un blocco da ciò che ho capito. – Seth

risposta

12

È possibile che i thread trascorrano la maggior parte del tempo in attesa dell'IO? Leggendo più file alla volta, è possibile che il disco si stacchi di più rispetto a una singola operazione. È possibile che tu possa migliorare le prestazioni usando una lettura di thread singolo in sequenza, ma poi distribuendo la decompressione legata alla CPU per separare i thread ... ma potresti effettivamente scoprire che hai solo bisogno di un solo thread per eseguire la decompressione in ogni caso, se il disco è più lento del processo di decompressione stesso.

Un modo per testare questo è copiare i file che richiedono la decompressione su un ramdisk e utilizzare ancora il codice corrente. Sospetto che scoprirai che sei legato alla CPU e che tutti i processori sono quasi sempre occupati.

(si dovrebbe anche prendere in considerazione quello che stai facendo con i file decompressi. Stai scrivendo quelle su disco? Se è così, ancora una volta c'è la possibilità che si sta fondamentalmente in attesa di un disco di santa ragione.)

+0

Non sto scrivendo i file decompressi sul disco. Sto leggendo i file compressi in memoria usando GZipStream, creando un TextREader per estrarre ciò che ho bisogno di inserirlo nella collezione imageFiles nel codice sopra. Potrei provare il tuo suggerimento sul disco RAM però. – Seth

+0

@Seth: nota che il suggerimento di ramdisk è davvero * solo * per verificare che tu sia legato all'IO piuttosto che alla CPU.Se è così, allora finirai per trasferire il costo alla fase "copia i dati sul ramdisk". –

+0

Ricordate quei driver del software di potenziamento del turbo del disco rigido anni fa? Hanno reso l'I/O del disco più veloce comprimendo i dati in memoria e quindi scrivendo i dati compressi sul disco. – dthorpe

0

C'è qualche possibilità che il tuo metodo statico stia condividendo qualsiasi risorsa globale tra le sue chiamate. Perché in questo caso questo metodo statico sarà chiamato in modo sequenziale e nessun beneficio parallelo. Puoi inserire il tuo codice di classe fileGrouping?

Problemi correlati