2012-12-12 38 views
25

情景:我有一個示例應用程序,我有3個不同的系統配置 -基於no的線程配置。 CPU-核心

- 2 core processor, 2 GB RAM, 60 GB HHD, 
- 4 core processor, 4 GB RAM, 80 GB HHD, 
- 8 core processor, 8 GB RAM, 120 GB HHD 

爲了有效地利用我的應用程序的H/W能力,我想配置的沒有。在應用程序級別的線程。但是,我希望在徹底瞭解系統功能之後才能做到這一點。

難道有一些方法(系統/模式/工具)來確定系統的實力,參考最大和最小編號。的線程,它可以最佳服務&而不會損失任何效率和性能。通過這個,我只能配置我的應用程序的那些值,這些值將充分公正,併爲相應的硬件配置實現最佳性能。

已編輯1: 請問任何人請告訴任何關於如何爲特定的硬件配置設置基準的讀取。

Edited2: 爲了使它更直接 - 希望學習/瞭解的任何資源/寫起來,我可以閱讀一般/整體水平獲得關於線程的CPU管理一定的瞭解。

+0

我想查找最小值的最佳值。的線程/最大號碼。基於上述系統配置的示例應用程序的線程數量,以實現最佳性能和完整的資源利用率。 – Santosh

+1

如果你不想用「啓發式」的答案,剩下的只是實驗設計。嘗試一些設置,你一定會發現本地最大/最小值。 –

回答

57

要使用的最佳線程數取決於幾個因素,但主要是可用處理器的數量以及您的任務的CPU密集程度。 Java Concurrency in Practice提出如下正式的公式來估算最佳線程數:

N_threads = N_cpu * U_cpu * (1 + W/C) 

其中:

  • N_threads是最佳線程數
  • N_cpu是prcessors的數量,你可以得到從Runtime.getRuntime().availableProcessors();
  • U_cpu是目標CPU利用率(如果要使用全部可用資源,則爲1)
  • W/C爲t他的等待時間比來計算時間(0爲CPU密集型的任務,也許10或100慢速I/O任務)

因此,例如,在CPU綁定的情況下,您將有儘可能多的線程作爲CPU(有人主張使用這個數字+ 1,但我從來沒有看到它有重大差異)。

對於緩慢的I/O過程,例如Web爬蟲,如果下載頁面比處理頁面慢10倍,則W/C可能爲10,在這種情況下,使用100個線程將會很有用。

但是請注意,在實踐中存在一個上限(使用10,000個線程通常不會加快速度,而且在使用正常內存設置啓動它們之前,您可能會遇到OutOfMemoryError)。

如果您不瞭解應用程序運行環境的任何信息,這可能是您可以獲得的最佳估計值。在生產環境中分析您的應用程序可能使您可以微調設置。

雖然沒有嚴格相關,但您可能也對Amdahl's law感興趣,它旨在測量您可以從並行程序中獲得的最大加速。

+2

啊,好點,刪除我以前的評論。 –

+0

如何獲得W/C的估算值?我是否需要找到I/O vs Compute的確切時間? – AgentX

14

你可以提供給JVM的處理器的數量是這樣的:

Runtime.getRuntime().availableProcessors() 

從可用的處理器數量計算線程的最佳數量是不幸的是不平凡不過。這很大程度上取決於應用程序的特性,例如對於具有比處理器數量更多的線程的CPU綁定應用程序沒什麼意義,而如果應用程序主要是IO綁定的,則可能需要使用更多線程。您還需要考慮系統上是否運行了其他資源密集型進程。

我認爲最好的策略是根據經驗確定每個硬件配置的最佳線程數,然後在您的應用程序中使用這些數字。

+0

礦是一個CPU密集型的過程。另外,我可以獲得關於如何爲特定h/w配置設置基線的任何讀取。我可以通過任何方式查明特定處理器是否可以使用其所有可用資源,或者是否因其他軟件正在運行而被阻塞。 – Santosh

+3

@Santosh如果它是CPU密集型的,那麼使用'availableProcessors()'線程數應該接近最優。 – assylias

+0

我通常會添加一個小的常數因子來調度slop,以防其中一個線程在IO上被阻塞或什麼東西... –

2

使用VisualVm工具監視線程。首先在程序中創建最小線程並查看其性能。然後增加程序中的線程數量並再次分析其性能。可以幫助您。

15

我的建議是提供配置和命令行開關來分配每臺機器的線程數。在用戶/管理員沒有明確配置應用程序的情況下,使用基於Runtime.getRuntime()。availableProcessors()的啓發式,如其他答案所示。我強烈建議對獨家啓發式基於線程到核心猜測,有以下幾個原因:SMT機型如英特爾:

  • 大多數現代硬件朝着越來越曖昧類型的「硬件線程」的運動超線程和AMD的計算模塊使公式複雜化(下面詳細介紹),並且在運行時查詢這些信息可能很困難。

  • 大多數現代硬件都具有turbo功能,可根據活動核心和環境溫度縮放速度。隨着渦輪增壓技術的進步,速度範圍(ghz)增加。一些最近的英特爾和AMD芯片的範圍可以從2.6ghz(所有核心活動)到3.6ghz(單/雙核心活動),與SMT結合可以意味着每個線程在前一個設計中獲得1.6ghz - 2.0ghz的有效吞吐量。目前沒有辦法在運行時查詢此信息。

  • 如果您沒有強有力的保證,您的應用程序將成爲在目標系統上運行的唯一進程,那麼盲目消耗所有cpu資源可能不會取悅用戶或服務器管理員(取決於軟件是否是用戶應用或服務器應用)。

有知道發生了什麼事情的機器在運行時,其餘內,沒有與自己家裏軋多任務內核更換整個操作系統沒有可靠的方法。您的軟件可以嘗試通過查詢流程並在CPU負載等情況下進行窺視來進行有根據的猜測,但這樣做很複雜,而且有用性僅限於特定類型的應用程序(您的資格可能符合),並且通常受益於或需要提升或特權訪問級別。

  • 現代病毒掃描儀現在通過設置現代操作系統提供的特殊優先級標誌來工作,他們讓操作系統告訴他們什麼時候「系統空閒」。操作系統的決策基礎不僅僅是CPU負載:它還考慮用戶輸入和可能由電影播放器​​設置的多媒體標誌等。對於大多數空閒的任務來說,這很好,但對於像你這樣的CPU密集型任務無用。分佈式家庭計算應用程序(BOINC,Folding @ Home等)通過定期查詢運行進程和系統CPU負載來工作 - 可能每秒或半秒一次。如果在不屬於應用程序的進程中檢測到連續多個查詢的負載,那麼應用程序將暫停計算。一旦某些查詢的負載變低,它就會恢復。由於CPU負載讀數對於短暫尖峯而言是臭名昭着的,所以需要多個查詢。還有一些注意事項:1.仍然鼓勵用戶手動重新配置BOINC以適應他們的機器規格。 2.如果BOINC在沒有Admin權限的情況下運行,那麼它不會意識到其他用戶啓動的進程(包括某些服務進程),所以它可能會不公平地與CPU資源進行競爭。

關於SMT(超線程,計算模塊):

大多數的SMT將作爲硬件核心報告或線程這些天,橫跨每個核心縮放時這通常不是一件好事,因爲一些應用程序進行優化一個SMT系統。更糟糕的是,查詢核心是共享的(SMT)還是專用核心往往不能產生預期的結果。在某些情況下,操作系統本身根本不知道(例如,Windows 7並不知道AMD Bulldozer的共享核心設計)。如果您可以獲得可靠的SMT計數,那麼經驗法則是將每個SMT計算爲CPU密集型任務的半線程數,並將其作爲大多數空閒任務的完整線程。但實際上,SMT的重量取決於其做什麼樣的計算,以及目標體系結構。例如,英特爾和AMD的SMT實施方式幾乎相反,英特爾在運行並行加載整數和分支操作的任務方面表現強勁。 AMD公司在並行運行SIMD和內存操作方面表現強勁。

關於渦輪增壓特點:

大多數CPU的這些天有內置的Turbo支持,進一步減輕了非常有效的價值得到了來自全國各地的系統的所有核心縮放。更糟糕的是,渦輪增壓功能有時基於系統的實際溫度,與CPU負載相同,所以塔本身的冷卻系統本身對速度的影響與CPU規格相同。例如,在特定的AMD A10(推土機)上,我觀察到它在兩個線程上運行在3.7ghz。當第三個線程開始時,它降至3.5ghz,而第四個線程開始時降至3.4ghz。由於它是一個集成的GPU,當四個線程加上GPU工作時(A10 CPU在高負載情況下內部優先於GPU),它一路下降到大約3.0ghz;但仍可以通過2個線程和GPU激活來召集3.6ghz。由於我的應用程序使用了CPU和GPU,這是一個重要的發現。通過將進程限制爲兩個CPU綁定線程(另外兩個共享內核仍然有用,它們作爲GPU服務線程 - 能夠喚醒並快速響應以將新數據推送到GPU),我能夠提高整體性能,如所須)。

...但與此同時,我的4倍線程應用程序可能在安裝了更高質量的冷卻設備的系統上執行得更好。這一切都非常複雜。

結論:沒有很好的答案,並且由於CPU SMT/Turbo設計領域不斷髮展,我懷疑不久將會有很好的答案。你今天制定的任何體面的啓發式可能不會在明天產生理想的結果。所以我的建議是:不要浪費太多時間。粗略猜測一些基於核心計數的東西,這些核心計數非常適合本地目的,允許它被config/switch覆蓋,然後繼續。

4

我同意這裏的其他答案,推薦最佳猜測方法,並提供配置以覆蓋默認值。此外,如果您的應用程序特別佔用大量CPU資源,則可能需要考慮將應用程序「固定」到特定處理器。

你不說你的主要操作系統是什麼,或者你是否支持多種操作系統,但大多數人都有這種方式。例如,Linux有taskset

一種常用的方法是避免CPU 0(始終由OS使用),並將應用程序的cpu親和性設置爲位於同一套接字中的一組CPU。

使應用程序的線程遠離cpu 0(並且,如果可能,遠離其他應用程序)通常會通過減少任務切換量來提高性能。

將應用程序保留在一個套接字上可以通過減少緩存失效進一步提高性能,因爲應用程序的線程在cpus之間切換。

與其他所有情況一樣,這高度依賴於您運行的機器的體系結構以及其他運行的應用程序。

1

我在這裏使用這個Python腳本來確定用最佳參數和人體工程學啓動我的Java應用程序的內核數量(以及內存等)。 PlatformWise on Github

它的工作原理是這樣的:編寫一個python腳本,在上面的腳本中調用getNumberOfCPUCores()以獲取核心數量,使用getSystemMemoryInMB()獲取RAM。您可以通過命令行參數將該通知傳遞給您的程序。然後您的程序可以根據核心數量使用適當數量的線程。

1

在應用程序級別創建線程是好的,而在多核處理器中,單獨的線程在內核上執行以提高性能。爲了利用核心處理能力,最好實施線程。

什麼,我認爲:

  1. 一次僅1中,節目的線程將在1個核心上執行。
  2. 具有2個線程的相同應用程序將在2個核心上執行一半的時間。
  3. 與4個線程相同的應用程序將執行更快的4核心。

所以你開發的應用程序應該有線程級< =無芯的。

線程執行時間由操作系統管理,是一個高度不可預測的活動。 CPU執行時間被稱爲時間片或量子。如果我們創建了越來越多的線程,操作系統花費了這個時間片的一小部分來決定哪個線程先行,從而減少了每個線程獲得的實際執行時間。換句話說,如果有大量線程排隊,每個線程都會做更少的工作。

閱讀此內容以瞭解如何真正利用cpu核心的簡單內容。 csharp-codesamples.com/2009/03/threading-on-multi-core-cpus/

1

不幸的是,從可用處理器的數量計算最佳線程數不是微不足道的。這很大程度上取決於應用程序的特性,例如對於具有比處理器數量更多的線程的CPU綁定應用程序沒什麼意義,而如果應用程序主要是IO綁定的,則可能需要使用更多線程。您還需要考慮系統上是否運行了其他資源密集型進程。