2013-01-05 12 views
6

मैं सिर्फ लेख 'Futures Done Right', और मुख्य बात यह है कि कि मौजूदाभविष्य composability, और बढ़ावा देने :: wait_for_all

से समग्र वायदा बनाने मैं देख रहा हूँ C++ 11 वादों की कमी है प्रतीत हो रहा है पढ़ अभी boost::wait_for_any

लेकिन निम्न उदाहरण पर विचार के प्रलेखन पर:

int calculate_the_answer_to_life_the_universe_and_everything() 
{ 
    return 42; 
} 

int calculate_the_answer_to_death_and_anything_in_between() 
{ 
    return 121; 
} 

boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything); 
boost:: future<int> fi=pt.get_future(); 
boost::packaged_task<int> pt2(calculate_the_answer_to_death_and_anything_in_between); 
boost:: future<int> fi2=pt2.get_future(); 

.... 


int calculate_the_oscillation_of_barzoom(boost::future<int>& a, boost::future<int>& b) 
{ 
    boost::wait_for_all(a,b); 
    return a.get() + b.get(); 
} 

boost::packaged_task<int> pt_composite(boost::bind(calculate_the_oscillation_of_barzoom, fi , fi2)); 
boost:: future<int> fi_composite=pt_composite.get_future(); 

composability के लिए इस दृष्टिकोण के साथ गलत क्या है? क्या यह composability प्राप्त करने के लिए एक वैध तरीका है? क्या हमें इस पैटर्न पर कुछ सुरुचिपूर्ण वाक्य रचनात्मक edulcorant की जरूरत है?

उत्तर

5

when_any और when_all वायदा लिखने के लिए पूरी तरह से वैध तरीके हैं। वे दोनों समानांतर संरचना से मेल खाते हैं, जहां समग्र ऑपरेशन या तो एक या सभी रचना किए गए संचालन के लिए इंतजार कर रहा है।

हमें भी अनुक्रमिक संरचना की आवश्यकता है (जो बूस्ट में नहीं है। थ्रेड)। यह, उदाहरण के लिए, future<T>::then फ़ंक्शन हो सकता है जो आपको एक ऐसे ऑपरेशन को कतारबद्ध करने की अनुमति देता है जो भविष्य के मूल्य का उपयोग करता है और भविष्य के तैयार होने पर चलता है। इसे स्वयं लागू करना संभव है, लेकिन एक दक्षता व्यापार के साथ। हर्ब सटर इस बारे में अपने recent Channel9 video में बात करते हैं।

N3428 सी ++ मानक पुस्तकालय में इन विशेषताओं (और अधिक) को जोड़ने के लिए एक मसौदा प्रस्ताव है। वे सभी लाइब्रेरी विशेषताएं हैं और भाषा में कोई नया वाक्यविन्यास नहीं जोड़ते हैं। इसके अतिरिक्त, N3328पुन: प्रयोज्य कार्यों (जैसे async/await का उपयोग सी # में) के लिए वाक्यविन्यास जोड़ने का प्रस्ताव है जो आंतरिक रूप से future<T>::then का उपयोग करेगा।

+0

हमारे पास पहले से ही लाइब्रेरी के रूप में पुन: प्रारंभ करने योग्य कार्य हैं: 'boost :: context' देखें। लाइब्रेरी का कार्यान्वयन 'when_all' कोड उदाहरण के कुछ भिन्न टेम्पलेट संस्करण होगा जो मैंने पोस्ट किया था? या क्या कोई और जादू है जिसे मैं याद कर रहा हूं? – lurscher

+0

बेशक, उन सभी packaged_tasks को किसी बिंदु पर थ्रेड पूल या 'asio :: io_service' को एसिंक निष्पादन के लिए सबमिट करने की आवश्यकता है, लेकिन जब कंप्यूटेशंस किया जाता है तो अर्थशास्त्र को प्रभावित नहीं किया जाना चाहिए – lurscher

+0

@ लांचर 'when_any' लागू करना मौजूदा पुस्तकालय सुविधाओं के शीर्ष पर पूरी तरह से संभव है, लेकिन आवश्यक रूप से कुशल नहीं है। मैं बड़ी संख्या में धागे पैदा करने, उन्हें बिल्कुल अवरुद्ध किए बिना, और उनमें से एक को जागने के लिए इंतजार किए बिना ऐसा करने का कोई तरीका नहीं देख सकता। दूसरी तरफ, यदि ऑपरेटिंग सिस्टम कुछ समर्थन प्रदान करता है, तो मानक पुस्तकालय विक्रेता के लिए एक और अधिक कुशल कार्यान्वयन संभव हो सकता है। –

3

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_compositecalculate_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 और भी अधिक सुविधा कार्यों प्रदान करता है।

संबंधित मुद्दे