edulcorant शब्द के उपयोग के लिए अंक। :)
आपके नमूना कोड के साथ समस्या यह है कि आप सब कुछ कार्यों में पैकेज करते हैं, लेकिन आप कभी भी अनुसूची निष्पादन के लिए उन कार्यों को नहीं!
int calculate_the_answer_to_life() { ... }
int calculate_the_answer_to_death() { ... }
std::packaged_task<int()> pt(calculate_the_answer_to_life);
std::future<int> fi = pt.get_future();
std::packaged_task<int()> pt2(calculate_the_answer_to_death);
std::future<int> fi2 = pt2.get_future();
int calculate_barzoom(std::future<int>& a, std::future<int>& b)
{
boost::wait_for_all(a, b);
return a.get() + b.get();
}
std::packaged_task<int()> pt_composite([]{ return calculate_barzoom(fi, fi2); });
std::future<int> fi_composite = pt_composite.get_future();
अगर मैं लिखना इस बिंदु पर
pt_composite();
int result = fi_composite.get();
मेरी कार्यक्रम हमेशा के लिए रोकेंगे। यह क्योंकि pt_composite
calculate_barzoom
, जो wait_for_all
पर अवरुद्ध है, जो दोनों fi
और fi2
, पर अवरुद्ध है पर अवरुद्ध है पूरा कभी नहीं होगा, जो कभी पूरा जब तक किसी को pt
या pt2
क्रमशः कार्यान्वित होगा न। और कोई भी उन्हें कभी निष्पादित नहीं करेगा, क्योंकि मेरा कार्यक्रम अवरुद्ध है!
तुम शायद मुझे मतलब कुछ इस तरह लिखने के लिए:
std::async(pt);
std::async(pt2);
std::async(pt_composite);
int result = fi_composite.get();
यह काम करेंगे। लेकिन यह बेहद अक्षम है - हमने दो धागे के काम करने के लिए तीन कार्यकर्ता धागे (तीन कॉल के माध्यम से async
) को जन्म दिया। वह तीसरा धागा - pt_composite
चल रहा है - तुरंत उत्पन्न हो जाएगा, और फिर बस तक pt
और pt2
तक चलने के बाद सो जाओ। कताई से बेहतर है, लेकिन यह से से अधिक महत्वपूर्ण नहीं है: इसका मतलब है कि हमारे थ्रेड पूल में कम से कम कार्यकर्ता होना चाहिए। प्रति सीपीयू कोर में केवल एक थ्रेड के साथ एक व्यावहारिक थ्रेड-पूल कार्यान्वयन में, और हर समय बहुत सारे कार्य आते हैं, इसका मतलब है कि हमारे पास एक सीपीयू कोर बस निष्क्रिय है, क्योंकि का कार्यकर्ता धागा था उस कोर पर चलना वर्तमान में wait_for_all
के अंदर अवरुद्ध है।
हम क्या चाहते हैं क्या करना एलान के तौर पर हमारे इरादे की घोषणा है:
int calculate_the_answer_to_life() { ... }
int calculate_the_answer_to_death() { ... }
std::future<int> fi = std::async(calculate_the_answer_to_life);
std::future<int> fi2 = std::async(calculate_the_answer_to_death);
std::future<int> fi_composite = std::when_all(fi, fi2).then([](auto a, auto b) {
assert(a.is_ready() && b.is_ready());
return a.get() + b.get();
});
int result = fi_composite.get();
और फिर सही काम करते हैं के लिए एक साथ पुस्तकालय और अनुसूचक काम है: किसी भी कार्यकर्ता धागा अंडे नहीं है कि कर सकते हैं ' टी तुरंत अपने कार्य के साथ आगे बढ़ें। यदि अंतिम उपयोगकर्ता को कोड की एक पंक्ति भी लिखनी है जो स्पष्ट रूप से सोती है, प्रतीक्षा करती है या ब्लॉक करती है, तो कुछ प्रदर्शन निश्चित रूप से खो जाता है।
दूसरे शब्दों में: स्पॉन अपने कार्यकाल से पहले कोई कार्यकर्ता धागा नहीं।
जाहिर है यह ++ पुस्तकालय समर्थन के बिना मानक सी में यह सब करने के लिए, संभव है; इस तरह पुस्तकालय स्वयं लागू किया गया है! लेकिन कई सूक्ष्म नुकसान के साथ, खरोंच से लागू करने के लिए यह एक बड़ा दर्द है; इसलिए यही एक अच्छी बात है कि पुस्तकालय का समर्थन जल्द ही आ रहा है।
आईएसओ प्रस्ताव N3428Roshan Shariff's answer में उल्लेख किया N3857 के रूप में अद्यतन किया गया है, और N3865 और भी अधिक सुविधा कार्यों प्रदान करता है।
हमारे पास पहले से ही लाइब्रेरी के रूप में पुन: प्रारंभ करने योग्य कार्य हैं: 'boost :: context' देखें। लाइब्रेरी का कार्यान्वयन 'when_all' कोड उदाहरण के कुछ भिन्न टेम्पलेट संस्करण होगा जो मैंने पोस्ट किया था? या क्या कोई और जादू है जिसे मैं याद कर रहा हूं? – lurscher
बेशक, उन सभी packaged_tasks को किसी बिंदु पर थ्रेड पूल या 'asio :: io_service' को एसिंक निष्पादन के लिए सबमिट करने की आवश्यकता है, लेकिन जब कंप्यूटेशंस किया जाता है तो अर्थशास्त्र को प्रभावित नहीं किया जाना चाहिए – lurscher
@ लांचर 'when_any' लागू करना मौजूदा पुस्तकालय सुविधाओं के शीर्ष पर पूरी तरह से संभव है, लेकिन आवश्यक रूप से कुशल नहीं है। मैं बड़ी संख्या में धागे पैदा करने, उन्हें बिल्कुल अवरुद्ध किए बिना, और उनमें से एक को जागने के लिए इंतजार किए बिना ऐसा करने का कोई तरीका नहीं देख सकता। दूसरी तरफ, यदि ऑपरेटिंग सिस्टम कुछ समर्थन प्रदान करता है, तो मानक पुस्तकालय विक्रेता के लिए एक और अधिक कुशल कार्यान्वयन संभव हो सकता है। –