2013-02-05 57 views
1

我有一個簡單的任務,很容易並行。基本上,必須在(大,幾個Gb)輸入文件的每一行上重複執行相同的操作。雖然我已經做了一個多線程版本,但我注意到我的I/O是瓶頸。我決定構建一個實用程序類,它涉及一個簡單的「文件讀取器」線程,它可以直接向前讀取並儘可能快地讀入循環緩衝區。然後,多個消費者可以打電話給這個班級並獲得他們的「下一行」。給定n個線程,每個線程我的起始行是文件中的第i行,並且通過添加n找到該線程的每個後續行。事實證明,這不需要鎖,幾個關鍵的原子操作就足以保存不變量。單文件閱讀器/多用戶模型:多線程程序的好主意?

我測試了代碼,它似乎更快,但經過第二次思考,我不知道爲什麼。將大文件分割成n個輸入文件(你可以'前進'到同一個文件中以達到同樣的效果,最少的預處理),然後讓每個進程只需調用iostream :: readLine就可以了它自己的塊? (因爲iostream也讀入它自己的緩衝區)。在多線程之間共享單個緩衝區似乎沒有任何固有的優勢,因爲工作人員實際上並不在相同的數據線上運行。另外,沒有什麼好方法我不認爲要並行化,以便它們在同一行上工作。我只是想了解我看到的性能增益,並知道它是'flukey'還是跨平臺可擴展/可重複的...

+1

除順序文件讀取之外的任何其他操作都會造成更多的傷害,尤其是對於需要實際的機械磁盤操作來「真正」讀取不在磁盤/驅動器緩存中的數據的大型文件。我不太確定你的單個循環緩衝區設計。單個文本行的線程間通信不會很有效 - 太多的原子操作和讀取線程在解析行時應該填充緩衝區。我可能會帶着一個更大的緩衝區實例池。 –

回答

0

當您I/O受限時,您可以通過使用兩個線程,一個讀取文件,第二個處理。這樣,閱讀將永遠不會等待處理(期待最後一行),並且您將閱讀100%。

緩衝區應該足夠大,足以讓消費者一次完成足夠的工作,這通常意味着它應該包含多行(我推薦至少4000個字符,但可能更多)。這將防止線程上下文切換成本不切實際地高。

單線程:

  • 讀1
  • 過程1
  • 讀2
  • 過程2
  • 讀3
  • 過程3

雙螺紋:

  • 讀1
  • 過程1 /讀取2
  • 過程2 /讀取3
  • 過程3

在某些平臺上,你可以得到同樣的加速也無緒,利用交疊I/O,但使用線程可能會更清晰。

只要您真的是I/O綁定,使用多個消費者線程將不會帶來好處。

+0

我也發現這個以及..但不iostream有它自己的緩衝區?爲什麼這是加速? – user2044555

+0

單線程工作時,需要處理緩衝區,然後纔讀取下一個緩衝區。如果某些讀取X需要新的數據,則需要等到讀取完整的新緩衝區爲止。該流沒有執行「推測性預讀」。在執行線程時,處理與讀取下一個緩衝區並行完成。 – Suma

0

在你的情況下,你的程序至少有兩個資源競爭CPU和硬盤。在單線程方法中,您請求數據,然後等待一個空閒的CPU讓HD傳輸它。然後,您處理數據,而HD空閒。這很糟糕,因爲兩個資源中的一個始終空閒。如果您有多個CPU或多個HD,則此更改一點。而且,在一些情況下,存儲器帶寬(即RAM連接)也是限制資源。

現在,您的解決方案是正確的,您使用一個線程來保持高清繁忙。如果這些線程阻塞等待HD,那麼OS就切換到處理一些數據的不同線程。如果它沒有任何數據,它會等待一些。這樣,至少在某些時候,CPU和HD將並行工作,從而提高整體吞吐量。請注意,除非您還有多個CPU,並且CPU是限制因素而不是HD,否則不能通過兩個以上的線程增加吞吐量。如果您也正在寫回一些數據,則可以通過寫入第二個硬盤的第三個線程來提高性能。否則,你不會從更多的線程獲得任何優勢。