2012-02-20 114 views
12

我一直在考慮std::async以及如何在未來的編譯器實現中使用它。但是,現在我有點卡住了感覺像設計缺陷的東西。std :: async - 與實現相關的用法?

std::async幾乎與實現有關,可能有兩個變種launch::async,一個將任務啓動到新線程中,另一個使用線程池/任務調度程序。

但是,根據用於實施std::async的這些變體中的哪一個,使用情況會有很大差異。

對於基於「線程池」的變體,您將能夠啓動大量小型任務,而不用擔心很多開銷,但是,如果其中一個任務在某個時間點阻塞了,該怎麼辦?

另一方面,「啓動新線程」變體不會遇到阻塞任務的問題,另一方面,啓動和執行任務的開銷將非常高。

線程池: +低開銷,-never曾經阻止

推出新的線程: +罰款塊,志高開銷

所以基本上取決於實施,我們使用std::async的方式會非常謹慎。如果我們有一個與一個編譯器兼容的程序,它可能會在另一個編譯器上運行。

這是設計嗎?或者我錯過了什麼?你會認爲這個和我一樣是個大問題嗎?

在當前的規範中,我缺少類似std::oversubscribe(bool)的內容,以便實現依賴於std::async的使用。

編輯:據我已閱讀,C++ 11標準文檔不會給任何提示關於發送到std::async的任務是否可能會阻塞。

+0

就像一個加法:http://en.cppreference.com/w/cpp/thread/async提供了一個非常簡單而實際的阻止'std :: async'調用的例子。 – KillianDS 2012-02-20 15:50:29

+0

您似乎認爲線程池具有固定的大小。實際上,很多都是動態調整大小的,所以阻塞不是問題。 – 2014-01-22 23:24:13

+0

@MooingDuck:TBB和Concrt都沒有「動態」大小的線程池。你知道哪些線程池是動態調整大小的?即使你有一個動態調整大小的線程池,你反而會遇到超額訂閱的問題,並且需要任何啓發式的開銷來跟蹤何時添加新線程和刪除舊線程。 – ronag 2014-01-22 23:31:42

回答

11

std::async任務,std::launch::async運行的政策推出「彷彿在一個新的線程」,所以線程池是不是真的支持---運行時將不得不推倒並重建中的每個之間的所有線程局部變量任務執行,這並不簡單。

這也意味着您可以期望以std::launch::async策略開始的任務可以同時運行。可能會有一個啓動延遲,如果你有更多的運行線程比處理器有更多的運行線程,那麼會有任務切換,但是它們應該是運行的,而不是因爲發生了等待另一個而發生死鎖。

實現可能會選擇提供擴展,它允許您的任務在線程池中運行,在這種情況下,需要由該實現來記錄語義。

+1

+1,用於「好像在新線程中」和線程局部變量。 – ronag 2012-02-20 15:46:07

+0

MSVC的異步使用線程池。我想象一下,當一個線程完成一個「任務」時,它會報告完成情況,然後重置它的線程本地,然後等待一個新的任務。這意味着用戶代碼永遠不必等待線程本地重置。 – 2014-01-22 23:26:36

+0

我不知道MSVC實現的細節,但是該標準要求'thread_local'變量在'future'準備好之前銷燬。 – 2014-01-23 16:57:26

1

我期望實現啓動新線程,並將線程池留給未來版本的C++來標準化它。有沒有使用線程池的實現?


MSVC根據其併發運行時初始使用線程池。根據STL Fixes In VS 2015, Part 2這已被刪除。 C++規範給實施者留下了一些空間讓聰明的人做事,但我認爲這不足以爲這個線程池實施留下足夠的空間。特別是我認爲該規範仍然要求thread_local對象將被銷燬和重建,但與ConcRT的線程池將不會支持。

+1

如果我沒有記錯,微軟在Going Native 2012會議期間宣佈'std :: async'會使用Concrt。我不知道gcc和clang有什麼計劃。 – ronag 2012-02-20 15:43:01

+0

MSVC確實在此時使用了一個線程池,最後我檢查了libC++和libstdC++都沒有使用池。 – 2014-01-22 23:28:28

相關問題