2012-05-30 63 views
4

我們目前正試圖通過在我們的Java應用程序中使用多線程來調整性能。 我們有一個長時間運行的串行任務,我們想分割成多個CPU核心。Java線程池:有更多的更小的任務,或更大的批量更少的任務

基本上我們有100,000個物品/要做的事情。

我現在的問題是,是它更好地做到:

選項1(僞):

for(i = 0; i < 100000; i++){ 
    threadpool.submit(new MyCallable("1 thing to do")) 
} 

這將增加10萬個可運行/可調用的線程池的隊列(當前的LinkedBlockingQueue)

或者是它更好地做到: 選項2(僞)

for(i = 0; i < 4; i++){ 
    threadpool.submit(new MyCallable("25000 things to do")) 
} 

我們已經嘗試過了選項1,但我們沒有注意到任何性能改進,儘管我們可以清楚地看到多個線程工作得像瘋了一樣,也使用了4個CPU內核。但我的感覺是,由於許多任務,選項1有一些開銷。我們還沒有嘗試過選項2,但我的感覺是,它可以加快速度,因爲開銷較小。我們基本上將這個列表分成4個大塊,而不是100000個單個項目。

對此有何看法?

感謝

+1

這不會有一個普遍的答案;這取決於「要做的事情」的性質。你必須嘗試。 –

+0

感謝您的幫助。我知道沒有普遍的答案,但我想了解每種方法。我們的用例是計算密集型的,而不是I/O限制。我們現在要實施選項2並比較結果。 – Christoph

回答

3

重要的是,您可以最大限度地減少上下文切換的數量,並最大限度地提高每個計算花費的工作量。實際上,如果您的任務正在計算,超過物理CPU數量將無濟於事。如果您的任務實際上執行了大量I/O並且I/O等待,那麼您希望擁有許多I/O,因此當一個塊阻塞時總會有大量「準備好」任務可用。如果你真的有25000件事情要做,事情就是計算,我可能會設置32個線程(比你有更多的CPU,但沒有額外的額外開銷),並且包含10-50個單元的如果這些單位相對較小,則向每個單位工作。

3

你的分析是正確的:會有在配料中的項目成本低(內存,上下文切換,和一般的指令數) - 至少,一般來說。

隨着單個任務變得越來越大,這變得越來越不重要 - 如果您已經花費了99%的時間來完成工作,而不是線程池開銷或對象創建,那麼您只能優化剩餘1%的這種方式。

1

那麼,這取決於你的用例。

表現明智,我認爲有更大塊的工作比更小的許多線程更好。上下文切換會更少,因此,您將能夠保存CPU週期和RAM。

當任務數量較小時,這可能並不重要,但是,如果您有10000個線程,那麼這很重要。

1

您的機器中有N個內核。你想利用你所有的內核,但是要花費最少的開銷。因此,如果任務的大小相等,則任務的最小數量可能爲N.如果它們不等於M * N,任務可能會更好,因爲它可能意味着即使某些任務相對較短,所有內核也同樣繁忙。例如一個核心做一項長期任務,另一個核心做三個短期任務。我在大多數用例中使用2-4的M值。

如果可以,您可以對較長時間運行的任務進行排序,以獲得最佳平衡。即在添加它們之前從最長到最短的任務進行排序。

例如如果您有8個內核,則可能會發現8個任務對於CPU綁定處理是最佳的。對於IO綁定處理或需要不同時間的任務,2 * 8到4 * 8任務可能是最優的。

1

4個批次的問題可能是,如果其中一個在10分鐘內完成,其中三個爲20分鐘,則1個核心將不會使用10分鐘,而其他3個線程將處理3個核心的項目。但是你的頭腦是正確的。但驗證的唯一方法是檢查它,因爲很多事情取決於您的數據。

相關問題