Which std::async implementations use thread pools?

后端 未结 1 1217
我寻月下人不归
我寻月下人不归 2020-11-28 06:10

One of the advantages of using std::async instead of manually creating std::thread objects is supposed to be that std::async can use t

相关标签:
1条回答
  • 2020-11-28 06:47

    Black-Box Test

    Though "white box" check can be done via inspecting boost, libstdc++ or libc++ sources, or checking documentation like just::thread or MSVC Concurrency Runtime, but I can not deny myself the pleasure of writing C++11 code!

    I have made 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
    

    As can be seen - MSVC does reuse threads, i.e. it is very likely that it's scheme is some kind of thread pool.

    0 讨论(0)
提交回复
热议问题