草庐IT

c++ - 哪些 std::async 实现使用线程池?

coder 2023-05-02 原文

使用 std::async 而不是手动创建 std::thread 对象的优点之一应该是 std::async 可以在后台使用线程池来避免超额订阅问题。但是哪些实现可以做到这一点?我的理解是微软的实现可以,但是这些其他的 async 实现呢?

  • Gnu 的 libstdc++
  • LLVM 的 libc++
  • Just Software 的库
  • Boost(对于 boost::thread::async,而不是 std::async)

感谢您提供的任何信息。

最佳答案

黑盒测试

虽然“白盒”检查可以通过检查 boost、libstdc++ 或 libc++ 源或检查文档如 just::thread 来完成或 MSVC Concurrency Runtime ,但我不能否认自己编写 C++11 代码的乐趣!

我做了black-box test :

LIVE DEMO

#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_RESULT_OF_USE_DECLTYPE
#include <boost/exception/exception.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/move/iterator.hpp>
#include <boost/phoenix.hpp>
#include <boost/thread.hpp>
#include <boost/config.hpp>

#include <unordered_set>
#include <functional>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <ostream>
#include <cstddef>
#include <string>
#include <vector>
#include <future>
#include <thread>
#include <chrono>
#include <mutex>

// _____________________[CONFIGURATION]________________________ //
namespace async_lib = std;
const bool work_is_sleep = false;
// ____________________________________________________________ //

using namespace std;
using boost::phoenix::arg_names::arg1;
using boost::thread_specific_ptr;
using boost::back_move_inserter;
using boost::type_name;
using boost::count_if;
using boost::copy;

template<typename Mutex>
unique_lock<Mutex> locker(Mutex &m)
{
    return unique_lock<Mutex>(m);
}

void do_work()
{
    if(work_is_sleep)
    {
        this_thread::sleep_for( chrono::milliseconds(20) );
    }
    else
    {
        volatile double result=0.0;
        for(size_t i=0; i!=1<<22; ++i)
            result+=0.1;
    }
}

int main()
{
    typedef thread::id TID;
    typedef async_lib::future<TID> FTID;

    unordered_set<TID> tids, live_tids;
    vector<FTID> ftids;
    vector<int> live_tids_count;
    async_lib::mutex m;
    generate_n
    (
        back_move_inserter(ftids), 64*thread::hardware_concurrency(),
        [&]()
        {
            return async_lib::async([&]() -> TID
            {
                static thread_specific_ptr<bool> fresh;
                if(fresh.get() == nullptr)
                    fresh.reset(new bool(true));
                TID tid = this_thread::get_id();
                locker(m),
                    live_tids.insert(tid),
                    live_tids_count.push_back(int(live_tids.size()) * (*fresh ? -1 : 1));
                do_work();
                locker(m),
                    live_tids.erase(tid);
                *fresh = false;
                return tid;
            });
        }
    );
    transform
    (
        begin(ftids), end(ftids),
        inserter(tids, tids.end()),
        [](FTID &x){return x.get();}
    );

    cout << "Compiler = " << BOOST_COMPILER                             << endl;
    cout << "Standard library = " << BOOST_STDLIB                       << endl;
    cout << "Boost = " << BOOST_LIB_VERSION                             << endl;
    cout << "future type = " << type_name<FTID>()                       << endl;
    cout << "Only sleep in do_work = " << boolalpha << work_is_sleep    << endl;
    cout << string(32,'_')                                              << endl;
    cout << "hardware_concurrency = " << thread::hardware_concurrency() << endl;
    cout << "async count = " << ftids.size()                            << endl;
    cout << "unique thread id's = " << tids.size()                      << endl;
    cout << "live threads count (negative means fresh thread):"                ;
    copy(live_tids_count, ostream_iterator<int>(cout," "));        cout << endl;
    cout << "fresh count = " << count_if(live_tids_count, arg1 < 0)     << endl;
}

Compiler = Microsoft Visual C++ version 11.0
Standard library = Dinkumware standard library version 540
Boost = 1_53
future type = class std::future<class std::thread::id>
Only sleep in do_work = false
________________________________
hardware_concurrency = 4
async count = 256
unique thread id's = 4
live threads count (negative means fresh thread):-1 -2 2 2 -3 -4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4
 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
fresh count = 4

Compiler = Microsoft Visual C++ version 11.0
Standard library = Dinkumware standard library version 540
Boost = 1_53
future type = class std::future<class std::thread::id>
Only sleep in do_work = true
________________________________
hardware_concurrency = 4
async count = 256
unique thread id's = 34
live threads count (negative means fresh thread):-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 18 18 18 18 18 18 18 18 18 18 18 18 18
 18 18 18 18 -19 19 -20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 -21 21 21 -22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 -
23 23 23 23 -24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 -25 25 25 25 25 -26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26
26 26 26 -27 27 27 27 27 27 -28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 -29 29 29 29 29 29 29 -30 30 30 30 30 30 30 30 30 30
 30 30 30 30 30 30 30 30 30 30 30 30 30 30 -31 31 31 31 31 31 31 31 -32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 -33 33
 33 33 33 33 33 33 33 -34 34 34 34 34 34 34 34 34 11 12 11 12 13 14 15 16 15 10 11 12 13 14
fresh count = 34

Compiler = Microsoft Visual C++ version 11.0
Standard library = Dinkumware standard library version 540
Boost = 1_53
future type = class boost::future<class std::thread::id>
Only sleep in do_work = false
________________________________
hardware_concurrency = 4
async count = 256
unique thread id's = 256
live threads count (negative means fresh thread):-1 -2 -2 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -3 -4 -4 -4 -4 -4 -4 -4
 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -2 -3 -3 -3 -3 -4 -4 -4 -4 -2 -2 -2 -2 -3
 -2 -2 -3 -1 -2 -2 -3 -3 -1 -2 -1 -2 -3 -2 -2 -2 -2 -1 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -3 -3 -2 -2 -2 -2 -3 -3 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2
 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -3 -1 -2 -1 -2 -1 -2 -1 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -3 -3 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2
 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -3 -3 -2 -2 -3 -1 -2 -1 -2 -2 -2 -3 -2 -3 -1 -2 -2 -2 -3 -2 -3 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2
 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -3 -3 -3 -2 -2 -2 -3
fresh count = 256

Compiler = Microsoft Visual C++ version 11.0
Standard library = Dinkumware standard library version 540
Boost = 1_53
future type = class boost::future<class std::thread::id>
Only sleep in do_work = true
________________________________
hardware_concurrency = 4
async count = 256
unique thread id's = 256
live threads count (negative means fresh thread):-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -2
8 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65
-66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102
 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132
 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162
 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192
 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222
 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252
 -253 -254 -255 -256
fresh count = 256

Compiler = GNU C++ version 4.8.0-alpha20121216 20121216 (experimental)
Standard library = GNU libstdc++ version 20121216
Boost = 1_53
future type = std::future<std::thread::id>
Only sleep in do_work = false
________________________________
hardware_concurrency = 4
async count = 256
unique thread id's = 1
live threads count (negative means fresh thread):-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
fresh count = 1

Compiler = GNU C++ version 4.8.0-alpha20121216 20121216 (experimental)
Standard library = GNU libstdc++ version 20121216
Boost = 1_53
future type = boost::future<std::thread::id>
Only sleep in do_work = false
________________________________
hardware_concurrency = 4
async count = 256
unique thread id's = 122
live threads count (negative means fresh thread):-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -20 -21 -22 -23 -24 -25 -25 -26 -27 -28 -29 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -59 -60 -61 -62 -63 -64 -64 -64 -63 -61 -55 -48 -41 -33 -34 -27 -27 -28 -29 -29 -30 -31 -31 -30 -28 -29 -28 -28 -28 -29 -30 -30 -31 -30 -31 -31 -31 -32 -31 -26 -24 -25 -26 -25 -23 -23 -22 -20 -21 -19 -20 -20 -19 -20 -21 -21 -22 -21 -22 -23 -24 -24 -25 -26 -27 -25 -25 -25 -22 -23 -22 -23 -23 -24 -25 -26 -27 -27 -28 -29 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -51 -52 -53 -54 -55 -56 -57 -56 -54 -3 -3 -4 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -55 -56 -57 -58 -59 -60 -61 -61 -61 -62 -63 -64 -65 -64 -62 -63 -63 -61 -62 -61 -59 -60 -59 -57 -55 -56
fresh count = 256

Compiler = Clang version 3.2 (tags/RELEASE_32/final)
Standard library = libc++ version 1101
Boost = 1_53
future type = NSt3__16futureINS_11__thread_idEEE
Only sleep in do_work = false
________________________________
hardware_concurrency = 4
async count = 256
unique thread id's = 255
live threads count (negative means fresh thread):-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -121 -122 -122 -123 -123 -124 -125 -126 -127 -126 -127 -128 -129 -129 -128 -129 -128 -129 -129 -128 -129 -129 -128 -126 -127 -128 -128 -129 -129 -130 -129 -129 -128 -129 -129 -130 -131 -132 -133 -134 -135 -136 -134 -132 -133 -134 -134 -133 -132 -133 -132 -133 -134 -133 -131 -129 -127 -124 -125 -121 -119 -120 -118 -119 -118 -117 -115 -111 -107 -105 -106 -103 -100 -97 -95 -96 -94 -90 -87 -81 -73 -74 -71 -72 -73 -74 -75 -70 -71 -66 -60 -59 -60 -61 -62 -63 -64 -61 -58 -55 -55 -52 -53 -54 -54 -55 -56 -56 -57 -54 -55 -56 -56 -57 -57 -58 -56 -54 -55 -56 -56 -57 -58 -58 -59 -58 -58 -58 -58 -59 -60
fresh count = 256

可以看出 - MSVC 确实重用线程,即它的方案很可能是某种线程池。

关于c++ - 哪些 std::async 实现使用线程池?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15666443/

有关c++ - 哪些 std::async 实现使用线程池?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐