2017-07-14 77 views
8

是否有明確設置/限制std::async和相關類使用的並行度(=單獨線程數)的方法?與std :: async並行的控制程度

Perusing the thread support library還沒有出現任何有希望的東西。

盡我所知,std::async實現(通常是?)在內部使用線程池。是否有標準化的API來控制它?

對於背景:我在設置(共享羣集),我必須手動限制使用的核心數量。如果我沒有做到這一點,負載分擔調度程序會發生變化,我會受到懲罰。特別是,std::thread::hardware_concurrency()沒有保存任何有用的信息,因爲物理核心的數量與我所處的約束無關。

這裏有一個相關的代碼(在C++ 17並行TS,可能會被使用parallel std::transform寫):

auto read_data(std::string const&) -> std::string; 

auto multi_read_data(std::vector<std::string> const& filenames, int ncores = 2) -> std::vector<std::string> { 
    auto futures = std::vector<std::future<std::string>>{}; 

    // Haha, I wish. 
    std::thread_pool::set_max_parallelism(ncores); 

    for (auto const& filename : filenames) { 
     futures.push_back(std::async(std::launch::async, read_data, filename)); 
    } 

    auto ret = std::vector<std::string>(filenames.size()); 
    std::transform(futures.begin(), futures.end(), ret.begin(), 
      [](std::future<std::string>& f) {return f.get();}); 
    return ret; 
} 

從設計的角度來看我期待有std::execution::parallel_policy (從並行TS),以允許指定(事實上,這是我在我爲我的碩士論文設計的框架中是如何做到的)。但似乎並非如此。

理想情況下,我想爲C++ 11提供一個解決方案,但如果有一個用於更高版本的解決方案,我仍然想知道它(儘管我無法使用它)。

+0

爲什麼你使用'std :: async'開頭?線程池實現不符合標準,並且標準符合的將爲每個任務打開一個新線程。無論如何,它吸引 –

+0

@DavidHaim這似乎是最簡單的解決方案。我試圖儘可能少編寫代碼來並行處理這些函數調用,而且我希望能夠使用標準庫而不必使用它。顯然不是。 –

+1

只要委員會堅持浪費時間在覈心語言功能上而不是重要的現代功能上,我們就會被迫自己寫解決方案。 –

回答

4

No. std::async是不透明的,你無法控制它對線程,線程池或其他任何東西的使用。事實上,你甚至不能保證它會使用線程 - 它可能會在同一個線程中執行(可能,請注意下面的@ T.C。註釋),並且這樣的實現仍然是一致的。

C++線程庫從來不應該處理線程管理的操作系統/硬件細節的微調,所以我擔心,在你的情況下,你將不得不自己編寫適當的支持,可能使用OS提供的線程控制原語。

+0

「,這樣的實現仍然符合」不是沒有使用線程局部變量的英雄努力。 –

+0

注意我正在使用'std :: launch :: async' - 這保證使用(「as if」)新線程(§30.6.8/ 3.1)。 –

+0

@ T.C。是的,沒有想到它。 – SergeyA

2

正如其他人所指出的,std::async不會讓你這樣做。

然而

你描述的Executors簡單的用例,其目前仍然存在C++標準化的設計空間的一個反彈,特別是在Study Group 1: Concurrency現在。

由於閱讀WG21標準提案可能是一個難題,他們的作者有助於鏈接到prototype header-only reference implementationsome example code

它甚至還包括一個靜態的線程池,以及幾乎正是你想要的一個例子: async_1.cpp

#include <experimental/thread_pool> 
#include <iostream> 
#include <tuple> 

namespace execution = std::experimental::execution; 
using std::experimental::static_thread_pool; 

template <class Executor, class Function> 
auto async(Executor ex, Function f) 
{ 
    return execution::require(ex, execution::twoway).twoway_execute(std::move(f)); 
} 

int main() 
{ 
    static_thread_pool pool{1}; 
    auto f = async(pool.executor(), []{ return 42; }); 
    std::cout << "result is " << f.get() << "\n"; 
} 

謝謝@賈裏德 - hoberock在P0668R0指着我的更簡單後續到P0443R1我已經在此答案的早期版本中引用。

這個簡化已被應用,現在有一篇論文描述的基本原理(P0761R0),以及P0443R2中標準措辭的簡單版本。


截至7月2017,我已經看到了這種遞送的唯一實際的猜測是:光良,在Concurrency TS的編輯---標準化車輛執行人---感覺「confident that it will make it into C++20"

相關問題