कोरटाइन में क्या हैं c ++ 20?
किन तरीकों से यह "Parallelism2" या / और "Concurrency2" (छवि के नीचे देखें) से अलग है?
नीचे की छवि ISOCPP की है।
कोरटाइन में क्या हैं c ++ 20?
किन तरीकों से यह "Parallelism2" या / और "Concurrency2" (छवि के नीचे देखें) से अलग है?
नीचे की छवि ISOCPP की है।
जवाबों:
एक अमूर्त स्तर पर, Coroutines ने निष्पादन की स्थिति होने के विचार से एक निष्पादन राज्य होने के विचार को विभाजित कर दिया।
SIMD (एकल निर्देश एकाधिक डेटा) में कई "निष्पादन के धागे" होते हैं, लेकिन केवल एक निष्पादन स्थिति होती है (यह सिर्फ कई डेटा पर काम करता है)। संभवतः समानांतर एल्गोरिदम इस तरह से एक सा है, जिसमें आपके पास अलग-अलग डेटा पर एक "प्रोग्राम" चलता है।
थ्रेडिंग में कई "निष्पादन के धागे" और कई निष्पादन राज्य हैं। आपके पास एक से अधिक कार्यक्रम हैं, और निष्पादन के एक से अधिक धागे हैं।
Coroutines में कई निष्पादन स्थितियां हैं, लेकिन निष्पादन का एक धागा नहीं है। आपके पास एक कार्यक्रम है, और कार्यक्रम में राज्य है, लेकिन इसमें निष्पादन का कोई धागा नहीं है।
कोरटाइन्स का सबसे आसान उदाहरण अन्य भाषाओं के जनरेटर या गणनाकर्ता हैं।
छद्म कोड में:
function Generator() {
for (i = 0 to 100)
produce i
}
Generator
कहा जाता है, और पहली बार यह कहा जाता है देता है 0
। इसकी स्थिति को याद किया जाता है (कोरटाइन्स के कार्यान्वयन के साथ कितना राज्य बदलता है), और अगली बार जब आप इसे कहते हैं तो यह जारी रहता है जहां इसे छोड़ा गया था। तो यह अगली बार 1 लौटाता है। फिर २।
अंत में यह लूप के अंत तक पहुंचता है और फ़ंक्शन के अंत में गिर जाता है; कोरटाइन समाप्त हो गया है। (यहां जो होता है, वह भाषा के आधार पर भिन्न होता है, जिसके बारे में हम बात कर रहे हैं; अजगर में, यह एक अपवाद फेंकता है)।
Coroutines C ++ में यह क्षमता लाती है।
दो प्रकार के कोरआउट हैं; स्टैकफुल और स्टैकलेस।
एक स्टैकलेस कोरआउट केवल स्थानीय चर को अपने राज्य और निष्पादन के स्थान पर संग्रहीत करता है।
एक स्टैकफुल कोरटाइन एक पूरे स्टैक (एक धागे की तरह) को स्टोर करता है।
स्टैकलेस कोराउटाइन बेहद हल्के वजन के हो सकते हैं। पिछले प्रस्ताव को मैंने पढ़ा है जिसमें मूल रूप से आपके कार्य को लंबोदर की तरह थोड़ा सा लिखना है; सभी स्थानीय चर एक वस्तु की स्थिति में जाते हैं, और लेबल का उपयोग उस स्थान से / पर कूदने के लिए किया जाता है, जहां कॉरआउट "मध्यवर्ती परिणाम" पैदा करता है।
एक मूल्य के उत्पादन की प्रक्रिया को "उपज" कहा जाता है, क्योंकि कोरटाइन सहकारी बहुपरत की तरह थोड़े होते हैं; आप कॉल करने वाले को वापस निष्पादन का बिंदु दे रहे हैं।
बूस्ट में स्टैकफुल कोरटाइन का कार्यान्वयन है; यह आपको आपके लिए एक फ़ंक्शन को कॉल करने देता है। स्टैकफुल कोरआउट अधिक शक्तिशाली होते हैं, लेकिन अधिक महंगे भी होते हैं।
एक साधारण जनरेटर की तुलना में कोराउटीन के लिए अधिक है। आप एक coroutine में एक coroutine की प्रतीक्षा कर सकते हैं, जो आपको एक उपयोगी तरीके से coroutines बनाने की सुविधा देता है।
Coroutines, जैसे कि, लूप और फ़ंक्शन कॉल, एक अन्य प्रकार की "संरचित गोटो" है जो आपको कुछ उपयोगी पैटर्न (जैसे राज्य मशीनों) को अधिक प्राकृतिक तरीके से व्यक्त करने की अनुमति देता है।
C ++ में Coroutines का विशिष्ट कार्यान्वयन थोड़ा दिलचस्प है।
अपने सबसे बुनियादी स्तर पर, यह कुछ कीवर्ड को C ++ में जोड़ता है co_return
co_await
co_yield
, साथ में कुछ पुस्तकालय प्रकार जो उनके साथ काम करते हैं।
एक फ़ंक्शन उसके शरीर में से एक होने से एक कोरटाइन बन जाता है। इसलिए उनकी घोषणा से वे कार्यों से अप्रभेद्य हैं।
जब उन तीन खोजशब्दों में से एक का उपयोग फ़ंक्शन बॉडी में किया जाता है, तो रिटर्न प्रकार और तर्कों की कुछ मानक अनिवार्य जांच होती है और फ़ंक्शन को कोरटाइन में बदल दिया जाता है। यह परीक्षा कंपाइलर को बताती है कि फंक्शन सस्पेंड होने पर फ़ंक्शन स्टेट को कहाँ स्टोर करना है।
सबसे सरल कोरआउट एक जनरेटर है:
generator<int> get_integers( int start=0, int step=1 ) {
for (int current=start; true; current+= step)
co_yield current;
}
co_yield
कार्यों के निष्पादन को निलंबित कर देता है, उस स्थिति को संग्रहीत करता है generator<int>
, फिर के current
माध्यम से मान लौटाता है generator<int>
।
आप लौटे पूर्णांकों पर लूप कर सकते हैं।
co_await
इस बीच आप एक दूसरे पर एक coroutine विभाजन की सुविधा देता है। यदि आप एक कॉरआउट में हैं और आपको प्रगति करने से पहले एक प्रतीक्षा योग्य चीज़ (अक्सर एक कॉरआउट) के परिणामों की आवश्यकता है, तो आप उस co_await
पर। यदि वे तैयार हैं, तो आप तुरंत आगे बढ़ें; यदि नहीं, तो जब तक आप इंतजार कर रहे हैं, तब तक आप तैयार नहीं हैं।
std::future<std::expected<std::string>> load_data( std::string resource )
{
auto handle = co_await open_resouce(resource);
while( auto line = co_await read_line(handle)) {
if (std::optional<std::string> r = parse_data_from_line( line ))
co_return *r;
}
co_return std::unexpected( resource_lacks_data(resource) );
}
load_data
एक कोरटाइन है जो std::future
नामित संसाधन को खोलने पर उत्पन्न होता है और हम उस बिंदु पर पार्स करने का प्रबंधन करते हैं जहां हमने डेटा का अनुरोध किया था।
open_resource
और read_line
शायद एसिंक्स कॉरआउट हैं जो एक फ़ाइल खोलते हैं और उससे लाइनें पढ़ते हैं। co_await
के निलंबित और तैयार राज्य जोड़ता है load_data
उनकी प्रगति के लिए।
सी ++ कोरटाइन इससे कहीं अधिक लचीले हैं, क्योंकि उन्हें उपयोगकर्ता-अंतरिक्ष प्रकारों के शीर्ष पर भाषा सुविधाओं के न्यूनतम सेट के रूप में लागू किया गया था। उपयोगकर्ता-अंतरिक्ष प्रकार प्रभावी रूप से क्या co_return
co_await
और क्या co_yield
अर्थ निर्धारित करते हैं - मैंने देखा है कि लोग इसका उपयोग करने के लिए विचित्र वैकल्पिक अभिव्यक्ति को लागू करते हैं, जैसे कि एक co_await
खाली वैकल्पिक स्वचालित रूप से खाली राज्य को बाहरी वैकल्पिक के लिए प्रचारित करता है:
modified_optional<int> add( modified_optional<int> a, modified_optional<int> b ) {
return (co_await a) + (co_await b);
}
के बजाय
std::optional<int> add( std::optional<int> a, std::optional<int> b ) {
if (!a) return std::nullopt;
if (!b) return std::nullopt;
return *a + *b;
}
;;
।
एक कोरआउट एक C फ़ंक्शन की तरह होता है जिसमें कई रिटर्न स्टेटमेंट होते हैं और जब दूसरी बार कॉल किया जाता है तो फ़ंक्शन की शुरुआत में निष्पादन शुरू नहीं होता है लेकिन पिछले निष्पादित रिटर्न के बाद पहले निर्देश पर होता है। यह निष्पादन स्थान सभी स्वचालित चर के साथ एक साथ सहेजा जाता है जो कि गैर-कोराउटीन कार्यों में स्टैक पर रहते हैं।
Microsoft से पिछले प्रायोगिक कोरूटाइन कार्यान्वयन ने कॉपी किए गए स्टैक का उपयोग किया था ताकि आप गहरी नेस्टेड फ़ंक्शन से भी वापस आ सकें। लेकिन इस संस्करण को C ++ समिति द्वारा अस्वीकार कर दिया गया था। आप इसे बूस्ट फाइबर लाइब्रेरी के साथ उदाहरण के लिए लागू कर सकते हैं।
कोराउटीन को माना जाता है (C ++ में) ऐसे कार्य जो किसी अन्य रूटीन को पूरा करने के लिए "प्रतीक्षा" करने में सक्षम होते हैं और निलंबित, रुके हुए, प्रतीक्षा के लिए, रूटीन को पूरा करने के लिए जो भी आवश्यक हो, प्रदान करते हैं। C ++ लोगों के लिए सबसे दिलचस्प है कि यह सुविधा है कि coroutines आदर्श रूप से कोई स्टैक स्पेस नहीं लेगा ... C # पहले से ही कुछ इस तरह से इंतजार कर रहा है और उपज प्राप्त कर सकता है लेकिन इसे प्राप्त करने के लिए C ++ को फिर से बनाना पड़ सकता है।
संगणना उन चिंताओं के पृथक्करण पर बहुत अधिक केंद्रित है जहां एक चिंता एक कार्य है जिसे कार्यक्रम पूरा करना है। चिंताओं के इस पृथक्करण को कई प्रकार से पूरा किया जा सकता है ... आमतौर पर किसी प्रकार का प्रतिनिधिमंडल होना चाहिए। संगोष्ठी का विचार यह है कि कई प्रक्रियाएं स्वतंत्र रूप से चल सकती हैं (चिंताओं को अलग करना) और एक conc श्रोता ’उन प्रत्यक्ष चिंताओं से उत्पन्न होता है, जहां जाना चाहिए। यह कुछ हद तक अतुल्यकालिक प्रबंधन पर निर्भर है। कॉन्सेप्ट के कई नंबर हैं जिनमें एस्पैक्ट ओरिएंटेड प्रोग्रामिंग और अन्य शामिल हैं। C # में 'डेलिगेट' ऑपरेटर है जो काफी अच्छी तरह से काम करता है।
समानतावाद संगोष्ठी की तरह लगता है और इसमें शामिल हो सकता है, लेकिन वास्तव में एक भौतिक निर्माण है जिसमें सॉफ्टवेयर के साथ अधिक या कम समानांतर फैशन में व्यवस्थित कई प्रोसेसर शामिल होते हैं जो कोड को अलग-अलग भागों में निर्देशित करने में सक्षम होते हैं जहां इसे चलाया जाएगा और परिणाम वापस प्राप्त होंगे तुल्यकालिक।