2014-01-13 85 views
1

什麼是效率最高如何從C++ 11中的線程返回值?從C++中的線程返回值11

vector<thread> t(6); 

for(int i = 0; i < 6; i++) 
    t[i] = thread(do_c); 

for(thread& t_now : t) 
    t_now.join(); 

for(int i = 0; i < 6; i++) 
    cout << /*the return of function do_c*/ 

另外,如果變化將有利於性能,隨意推薦另一個線程比std::thread

+0

你不小心一個字?從線程返回值,對嗎? –

+0

?你什麼意思?是 – Luka

+0

是的,但我想最有效的方式 – Luka

回答

4

啓動一個線程並終止它需要數百個機器週期。但這只是一個開始。線程之間的上下文切換(如果線程正在執行任何有用的事情時會發生)將重複消耗更多數百個機器週期。所有這些線程的執行上下文將消耗許多字節的內存,這反過來會弄亂許多行緩存,從而妨礙了CPU在數百個機器週期中的又一個很大的努力。事實上,多任務處理是數百個機器週期的一個重要消費者。多任務處理僅在CPU功耗方面變得有利可圖當您設法獲得足夠的處理器以處理概念上獨立的數據塊(因此並行處理不會威脅到它們的完整性)並且大到足以顯示淨收益時與單處理器版本。

在所有其他情況下,多任務處理是在所有域,但一個固有低效:反應。任務可以對外部事件作出快速而準確的反應,最終來自外部H/W組件(無論是定時器的內部時鐘還是用於網絡流量的WiFi /以太網控制器)。

這種在不浪費CPU的情況下等待外部事件的能力是提高整體CPU效率的原因。就是這樣。
在其他性能參數方面(內存消耗時間內核調用內部的浪費,等等),推出一個新的線程是總的淨虧損

概括地說,多任務編程的技術歸結爲:

  • 識別所述外部I/O流,你將不得不處理
  • 考慮反應性的要求考慮(記住多個反應性=更少CPU /內存在99%的時間內高效運行)
  • 以合理的效率/易於維護的折中方式爲所需事件設置處理程序。

多處理器架構正在增加一個新的複雜程度,因爲現在任何程序都可以看作是一個擁有許多外部CPU的進程,可以用作額外的電源。但是你的問題似乎沒有任何關係。

的多任務處理效率的量度,最終將取決於給定的計劃預計以應付同時和一組給定的反應性限制外部事件數。

最後我來談談你的問題。

要應對外部事件,每一個新的樹枝或死昆蟲的位必須移動周圍的蟻丘是一個非常粗糙和低效的進場時間發動的任務。

您在您的處置許多強大的同步工具,這將讓你從(近)在(幾乎)沒有成本最優效率的單個任務範圍內的是一幫異步事件的反應。
通常情況下,在多個輸入阻塞等待,例如像Unix的口味select()或微軟的WaitForMultipleEvents()對口。

使用這些會給你一個性能提升無比超過幾十個CPU週期,你可以擠出你這個任務的結果收集優化項目的更大。

所以我的答案是:不要打擾優化線程設置。這不是問題。

你最好將時間花在重新考慮你的架構,這樣經過深思熟慮的線程少數可以取代無用CPU成羣的記憶豬當前的設計會催生。

+0

感謝您的解釋,neko-san。這讓我改變主意,決定不使用線程。 – Luka

+0

@Luka很高興能夠幫助您(和您的編譯器以及您的CPU)帶來許多不必要的痛苦;) –

+0

對不起,我錯誤地將您的帖子錯誤地提交了,請編輯它以註銷它... – Luka

6

首先std::thread不會返回一個值,但是在構造時傳遞給它的函數可能會非常好。

沒有辦法從std::thread對象中訪問函數的返回值,除非在線程上調用該函數後以某種方式保存它。

一個簡單的解決方案,例如,將引用傳遞給線程並將結果存儲在引用指向的內存中。對於線程,雖然必須注意不要引入數據競賽

考慮一個簡單的函數:

int func() { 
    return 1; 
} 

而且這個例子:

std::atomic<int> x{0}; // Use std::atomic to prevent data race. 

std::thread t{[&x] { // Simple lambda that captures a reference of x. 
    x = func();  // Call function and assign return value. 
}}; 

/* Do something while thread is running... */ 

t.join(); 

std::cout << "Value: " << x << std::endl; 

現在,而不是處理這個低級別的併發填充自己,你可以使用標準庫有人(一如既往)已經爲你解決了它。有std::packaged_taskstd::future這是設計與std::thread爲這種特殊類型的問題。在大多數情況下,它們也應該是,就像高效的一樣是自定義解決方案。

下面是使用std::packaged_taskstd::future等效例如:

std::packaged_task<int()> task{func}; // Create task using func. 
auto future = task.get_future();  // Get the future object. 

std::thread t{std::move(task)};  // std::packaged_task is move-only. 

/* Do something while thread is running... */ 

t.join(); 

std::cout << "Value: " << future.get() << std::endl; // Get result atomically. 

不要總是認爲事情是僅僅因爲它被認爲是「高級別」低效率。

+0

我的腦海裏浮現的問題是:什麼*功能*要求將證明使用一種設計的機制可以在腦海中並行處理大量數據以檢索單純的整數線程返回值?看起來更像我稱之爲語法驅動的軟件設計。隨着C++ 11多功能性的展示,這些解決方案非常漂亮,但它們可以在語法糖,恕我直言的結冰下隱藏大量的資源消耗。 –

+0

@kuroineko這一切都取決於我猜的域名。對於通用應用程序開發,我將使用標準化的類和函數來實現同事間的最大可理解性,而不是定製解決方案。是否有任何功能需求來證明使用抽象?那麼我想不出任何。但是缺乏功能性要求來證明抽象代碼的可維護性並不是不那麼重要。非功能性要求也很重要。 – Snps

+0

正如我所看到的,這是一個在易用性和浪費之間找到一個甜蜜點的問題,如果不是潛在危險的習慣。在那個具體情況下,我認爲值得關於舒適性的價格有點值得思考。我確實設計了嵌入式軟件十年左右,這可能是爲什麼看到投入這麼多資源以避免這麼小的努力往往會讓我緊張:)。 –