2011-11-10 94 views
5

我有以下代碼:爲什麼Parallel.ForEach循環不能提高性能?

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


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

DecompressAndReadGzFile是在同一個班級,這種方法被包含在一個靜態方法按照方法的名稱,我解壓和讀取GZ文件,很多很多的,即達。到1000,所以並行化的開銷是值得的。但是,我沒有看到好處。當我使用ANTS性能分析器時,我發現它們在完全相同的時間運行,就好像沒有發生並行化一樣。我還使用進程資源管理器檢查CPU核心,看起來有可能在兩個核心上完成工作,但一個核心似乎正在完成大部分工作。對於讓Parallel.ForEach並行解壓縮和讀取文件,我不理解什麼?

更新的問題:什麼是從文件列表中讀取信息的最快方法?

的問題(簡化):

  1. 有的。廣州文件(1200)大的列表。
  2. 每個文件都有一行包含「DATA:」的行,位置和行號不是靜態的,並且可以因文件而異。
  3. 我們需要後檢索的第一個數字「數據顯示:」(只是爲了簡單起見),並將其存儲在內存中的對象(如表)

在最初的問題,我用的是並行.ForEach循環,但我似乎沒有CPU綁定超過1核心。

+0

在「DecompressAndReadGzFile」中是否有任何同步? – SimonC

+0

不是我所知道的。雖然有一個imageFiles.Add的調用,它會自動添加我理解的鎖。 – Seth

回答

12

線程是否有可能花大部分時間等待IO?通過一次讀取多個文件,您可能會使磁盤比單個操作時多。有可能你可以通過單線程讀取順序來提高性能,但是隨後將CPU限制解壓縮分離出線程......但是實際上你可能會發現,只是真的需要一個線程來執行解壓縮,如果磁盤比解壓縮過程本身慢。

測試此方法的一種方法是將需要解壓縮的文件先複製到虛擬硬盤上,然後使用您當前的代碼。我懷疑你會發現你是CPU限制的,並且幾乎所有的處理器都在忙着。

(你也應該考慮你與解壓縮文件做什麼。你寫這些回磁盤?如果是的話,再有,你基本上是在等待顛簸盤的可能性。)

+0

我沒有將解壓縮的文件寫入磁盤。我正在使用GZipStream將壓縮文件讀入內存,創建一個TextReader來提取我需要將它放入上述代碼中的imageFiles集合中。我可能會嘗試你的RAM磁盤建議。 – Seth

+0

@Seth:請注意,ramdisk建議實際上只是驗證您是否受IO限制而不受CPU限制。如果是這樣的話,那麼你最終會將成本轉移到「將數據複製到虛擬盤」階段。 –

+0

多年前還記得那些硬盤驅動器的渦輪增壓軟件驅動嗎?他們通過壓縮內存中的數據,然後將壓縮數據寫入磁盤,使磁盤I/O更快。 – dthorpe

0

有沒有可能你的靜態方法在它的調用中共享任何全局資源。 因爲在這種情況下,這個靜態方法將被順序調用並且沒有並行的好處。 你可以把你的fileGrouping類代碼?