2015-01-15 157 views
1

基於this問題,我有一個類,其構造函數只做一些分配,然後有一個實際完成這項工作的成員函數。我應該創建多少個線程?

我知道我將要構建的對象數量在[2,16]的範圍內。實際的數字是一個用戶參數。

我在創造我的對象for循環這樣

for (int i = 0; i < n; ++i) { 
    roots.push_back(RKD<DivisionSpace>(...)); 
} 

然後在另一個for循環創建線程。每個線程對象的一大塊叫build(),基於這樣的邏輯:

如果矢量有n個元素,你有P個線程, 線程我只寫元素

[中/ P,( i + 1)n/p)。

因此,舉例來說,情況是這樣的:

std::vector<RKD<Foo>> foos; 
// here is a for loop that pushes back 'n' objects to foos 

// thread A   // thread B     // thread C 
foos[0].build(); foos[n/3 + 0].build(); foos[2 * n/3 + 0].build(); 
foos[1].build(); foos[n/3 + 1].build(); foos[2 * n/3 + 1].build(); 
foos[2].build(); foos[n/3 + 2].build(); foos[2 * n/3 + 2].build(); 
...     ...       ... 

我遵循的方法是確定的線程p這樣的數字:

p = min(n, P) 

其中n是我想要創建的對象的數量,並且P的返回值爲std::thread::hardware_concurrencydealing與C++ 11的功能有一些問題後,我讀了這一點:

即使hardware_concurrency實現,它不能依賴作爲直接映射到內核的數量。這是標準所說的返回值 - 硬件線程上下文的數量。並繼續說明 - 只應將此值視爲提示如果您的計算機啓用了超線程,則返回的值完全有可能是內核數量的兩倍。如果你想得到可靠的答案,你需要使用你的操作系統提供的任何設施。 - Praetorian

這意味着我應該改變方法,因爲這個代碼是要從幾個用戶執行(我的意思是不僅在我的系統中,許多人將運行該代碼)。所以,我想以一種既標準又高效的方式選擇線程的數量。由於對象的數量相對較少,是否有一些規則可以遵循或什麼?

+0

我不認爲你所提供的報價意味着你需要改變的方法;它只是說這個值可能是* logical *(或* virtual *)內核的數量,這很好 - 如果它啓用,您就希望利用超線程。如果您的處理器可以並行運行兩倍,那麼使用一半的線程沒有意義。 – bogdan

+0

@bogdan如果你能回答分析你的觀點,那會很棒,因爲現在對我來說還不太清楚:/ – gsamaras

+0

OpenMP定義了[一些環境變量](https://gcc.gnu.org/onlinedocs /libgomp/Environment-Variables.html),它可以用來選擇它將創建的最大線程數。你可以讓你的應用程序檢查具有相似名稱的變量,如果它們不是由用戶設置的,則回退到'std :: thread :: hardware_concurrency'。這就是我可能會做的。 – 5gon12eder

回答

1

只需挑選hardware_concurrency個線程的線程池,並按照先到先服務的原則排隊項目。

如果系統中的其他進程以某種方式獲得操作系統的優先級,那就這樣吧。這僅僅意味着少於分配的池大小(例如P - 1)可以同時運行。從第一個可用的線程池完成build()開始並不重要 - 一個項目將從隊列中選擇下一個項目。

要真正避免線程在同一核心競爭,你可以

  • 使用信號量(進程間信號量,如果要真正地協調從單獨的進程建設者線程)

  • 線程親和力(以防止OS在下一個時間片上將特定線程調度到不同的核心上);可惜我不認爲有標準,與平臺無關,設置線程關聯的方法(尚未)。

我看不出有什麼令人信服的理由,使之更加複雜

+0

「只需選擇hardware_concurrency線程的線程池」。你的意思是一個大小等於hardware_concurrency返回值的'std :: thread'池? – gsamaras

+0

是的。見例如這裏http://stackoverflow.com/questions/22569805/boost-thread-throwing-exception-thread-resource-error-resource-temporarilyuna_25570554#22570554(「瘋狂星期五獎金」) – sehe

+0

這個例子使用boost,這是我想要避免的,但是我明白了。所以每個線程只需要一個元素,不超過上述問題中的一個,對吧? – gsamaras

相關問題