प्रॉम्प्ट और प्रयोज्यता
एक सेवा को रीडिंग, ट्रांसफ़ॉर्मेशन और एग्रीगेशन को एक एसिंक्रोनस पाइपलाइन में कंपोज़ करना चाहिए। कॉलर टाइमआउट, डिस्कनेक्ट या संसाधन दबाव पर रद्द (कैनसल) कर सकता है; प्रत्येक चरण तब विफल हो सकता है जब अन्य कार्य पहले से चल रहे हों। शेड्यूलिंग, कम्प्लीशन सिग्नल्स, लाइफटाइम और फ़ॉलबैक पाथ्स को समझाने के लिए C++26 std::execution सेंडर/रिसीवर मॉडल का उपयोग करें।
यह कंकरेंसी एब्स्ट्रैक्शन की सीमाओं का परीक्षण करता है, न कि किसी एक लाइब्रेरी के सिंटैक्स को याद रखने का। मानक execution-control लाइब्रेरी सेंडर के वर्क ग्राफ़ को रिसीवर कम्प्लीशन हैंडलिंग से अलग करती है और कनेक्टेड एसिंक्रोनस स्टेट के लिए एक ऑपरेशन स्टेट का उपयोग करती है। एक मजबूत उत्तर कैंसलेशन, एरर सेमेंटिक्स और क्लीनअप को स्पष्ट अनुबंध (कॉन्ट्रैक्ट) बनाता है।
साक्षात्कारकर्ता क्या परीक्षण कर रहा है
- एक लेज़ी सेंडर, एक कनेक्टेड ऑपरेशन स्टेट और
startपर वास्तविक निष्पादन के बीच अंतर करना। - व्यावसायिक कोड में तदर्थ (ad hoc) थ्रेड्स बनाने के बजाय शेड्यूलर्स के साथ निष्पादन संसाधनों का प्रतिनिधित्व करना।
- कैंसलेशन को अपवाद के रूप में छिपाने के बजाय
set_value,set_errorऔरset_stoppedको अलग-अलग संभालना। - प्रत्येक चरण के माध्यम से स्टॉप अनुरोधों को प्रोपेगेट करना और स्टॉप के बाद नए साइड इफेक्ट्स को रोकना।
- समानांतर कार्य के लिए बैकप्रेशर, सीमाएं, अपवाद सुरक्षा और एग्रीगेशन की व्याख्या करना।
- मानक लाइब्रेरी अनुपलब्ध होने पर क्षमता पहचान (capability detection), एक अनुकूलता परत (compatibility layer) और सुसंगत परीक्षण प्रदान करना।
पहले पूछे जाने वाले स्पष्टीकरण
- क्या रीडिंग किसी स्थानीय फ़ाइल, नेटवर्क अनुरोध या डेटाबेस कर्सर से हो रही है? क्या चरण दोहराने योग्य हैं या बाहरी रूप से साइड-इफ़ेक्ट उत्पन्न करने वाले हैं?
- क्या कैंसलेशन का अर्थ तुरंत रुकना है, किसी नॉन-इंटरप्टिबल कॉल के बाद रुकना है, या कमिट किए गए परिणामों को रोल बैक करना है?
- पैरेललिज्म, मेमोरी, प्रति-आइटम टाइमआउट और समग्र समय सीमा (डेडलाइन) की सीमाएं क्या हैं?
- क्या एग्रीगेशन को इनपुट क्रम, स्थिर फ़्लोटिंग-पॉइंट परिणाम या दृश्यमान आंशिक परिणामों को संरक्षित करना चाहिए?
- क्या लक्षित कंपाइलर और लाइब्रेरी C++26 निष्पादन को लागू करते हैं, या केवल एक प्रयोगात्मक कार्यान्वयन को?
एक 30-सेकंड का उत्तर
मैं वैल्यू, एरर और स्टॉप्ड चैनलों के साथ एक कम्प्लीशन कॉन्ट्रैक्ट को परिभाषित करूँगा। कैंसलेशन उस कार्य को रोकता है जो शुरू नहीं हुआ है और इंटरप्ट करने योग्य चरणों को तुरंत प्रतिक्रिया देने की अनुमति देता है। प्रत्येक सेंडर लेज़ी रहता है; कनेक्ट करने से एक ऑपरेशन स्टेट बनता है, और start निष्पादन शुरू करता है। स्पष्ट शेड्यूलर निष्पादन संसाधनों के स्वामी होते हैं, जबकि पैरेललिज्म और कतार सीमाएं मेमोरी की रक्षा करती हैं। एग्रीगेटर ऑर्डरिंग और आंशिक-परिणाम नियमों को परिभाषित करता है। कैपेबिलिटी डिटेक्शन मानक कार्यान्वयन, एक कम्पैटिबिलिटी लाइब्रेरी, या एक सिंक्रोनस स्केलर पाथ का चयन करता है, जिसमें कैंसलेशन, एरर और परिणामों के लिए साझा परीक्षण होते हैं।
चरण-दर-चरण गहन विश्लेषण
1. लेज़ी वर्क ग्राफ़ बनाएं
एक रीड सेंडर को एक ट्रांसफ़ॉर्म सेंडर से और फिर एक एग्रीगेट सेंडर से कनेक्ट करें। then उत्पादित मानों को अगले नोड पर भेजता है, let_value परिणाम से एक और एसिंक्रोनस ऑपरेशन बना सकता है, और when_all पैरेलल शाखाओं का प्रतिनिधित्व करता है। कंपोज़िशन एक ग्राफ़ बनाता है; इसे निर्माण के दौरान I/O नहीं करना चाहिए।
2. कनेक्शन और लाइफटाइम को परिभाषित करें
सेंडर और रिसीवर के बीच connect एक ऑपरेशन स्टेट बनाता है; निष्पादन की अनुमति केवल start के बाद ही होती है। ऑपरेशन स्टेट का पता तब तक मान्य रहना चाहिए जब तक कि एसिंक्रोनस ऑपरेशन पूरा न हो जाए, इसलिए यह ऐसे स्टैक फ़्रेम में नहीं रह सकता जो वापस लौटने वाला हो। एक अनुरोध संदर्भ (रिक्वेस्ट कॉन्टेक्स्ट) या एसिंक्रोनस स्कोप को इसका स्वामी होना चाहिए और वैल्यू, एरर और स्टॉप्ड पाथ्स पर संसाधनों को रिलीज़ करना चाहिए।
3. शेड्यूलर्स को संसाधन दें
शेड्यूलर एक निष्पादन संसाधन का एक लाइटवेट हैंडल है। रीडिंग को I/O संसाधन पर और CPU ट्रांसफ़ॉर्मेशन को एक सीमित पैरेलल संसाधन पर रखें; स्टेज सीमाओं को व्यक्त करने के लिए on, starts_on, या continues_on का उपयोग करें। प्रति तत्व एक थ्रेड न बनाएं। मेमोरी और कॉन्टेक्स्ट स्विचिंग को नियंत्रित करने के लिए पैरेललिज्म, कतार की लंबाई और बैच आकार को सीमित करें।
4. stopped, error और value को प्रोपेगेट करें
वैल्यू कम्प्लीशन अगले चरण में प्रवेश करता है, एरर्स यूनिफ़ाइड एरर हैंडलिंग में प्रवेश करते हैं, और स्टॉप्ड कैंसलेशन हैंडलिंग में प्रवेश करता है। रिसीवर एनवायरनमेंट का स्टॉप टोकन एक कैंसलेशन ऑब्जर्वेशन पॉइंट है। ब्लॉकिंग सिस्टम कॉल्स को एक इंटरप्टिबल इंटरफ़ेस या सीमित टाइमआउट की आवश्यकता होती है; अन्यथा वे केवल लौटने के बाद ही प्रतिक्रिया दे सकते हैं। कैंसलेशन रोलबैक नहीं है: एक बार बाहरी राइट हो जाने के बाद, इडेम्पोटेंसी की, कंपंसेशन, या एक स्पष्ट अपरिवर्तनीय सीमा का उपयोग करें।
5. एक न्यूनतम कंपोज़िशन स्केच
कोड ग्राफ़ का आकार दिखाता है; वास्तविक रीड और थ्रेड-पूल सेंडर्स प्रोजेक्ट द्वारा प्रदान किए जाते हैं।
using namespace std::execution;
auto pipeline = read_sender()
| let_value([](Batch batch) {
return bulk_transform(batch, get_parallel_scheduler());
})
| then([](Transformed value) { return summarize(value); })
| upon_error([](std::exception_ptr error) { record_failure(error); })
| upon_stopped([] { record_cancellation(); });
auto state = connect(std::move(pipeline), receiver);
start(state);रिसीवर का स्वामित्व एक लाइव रिक्वेस्ट स्कोप के पास होना चाहिए जो अपने एनवायरनमेंट में एक स्टॉप टोकन प्रदान करता है। प्रोडक्शन कोड को केवल एक सामान्य विफलता को उजागर करने के बजाय चरण, बैच, समय सीमा और कैंसलेशन के कारण को भी रिकॉर्ड करना चाहिए।
6. पैरेलल एग्रीगेशन और साइड-इफ़ेक्ट सीमाएं
समानांतर ट्रांसफ़ॉर्मेशन के दौरान प्रति-कार्य स्थानीय स्थिति बनाए रखें और एग्रीगेशन पर एक परिभाषित क्रम में मर्ज करें। यदि अनऑर्डर्ड मर्जिंग की अनुमति है, तो गैर-सहयोगी (non-associative) फ़्लोटिंग-पॉइंट संचालन के कारण होने वाले अंतरों का उल्लेख करें; यदि स्थिर आउटपुट की आवश्यकता है, तो एक इंडेक्स या पार्टीशन सीक्वेंस को सुरक्षित रखें। बाहरी राइट से पहले स्टॉप टोकन की जाँच करें और कमिट के बाद एक इडेम्पोटेंसी की रिकॉर्ड करें। set_stopped का अर्थ यह नहीं है कि कमिट को पूर्ववत (undo) कर दिया गया था।
7. फ़ॉलबैक, परीक्षण और अवलोकन क्षमता
फ़ीचर-टेस्ट मैक्रोज़, कंपाइलर वर्ज़न और लाइब्रेरी क्षमताओं से एक मैट्रिक्स बनाएं। यदि मानक निष्पादन अनुपलब्ध है, तो एक कम्पैटिबिलिटी कार्यान्वयन आंतरिक सेंडर अनुबंध को बनाए रख सकता है; अन्यथा वैल्यू, एरर और स्टॉप्ड सेमेंटिक्स को सुसंगत रखते हुए एक सीमित थ्रेड पूल या सिंक्रोनस पाथ का उपयोग करें। खाली इनपुट, आंशिक बैच, बार-बार कैंसलेशन, एरर-बनाम-स्टॉप रेस, संसाधन थकावट (रिसोर्स एग्जॉशन), शुरुआती ऑपरेशन-स्टेट विनाश, और बार-बार शुरुआत का परीक्षण करें। थ्रूपुट, टेल लेटेंसी, कतार की लंबाई, कैंसलेशन प्रतिक्रिया समय और अधूरे कार्यों को बेंचमार्क करें।
उच्च गुणवत्ता वाला नमूना उत्तर
मैं पाइपलाइन को एक लेज़ी सेंडर ग्राफ़ के रूप में मॉडल करूँगा: रीड, पैरेलल ट्रांसफ़ॉर्म और एग्रीगेट प्रत्येक कम्प्लीशन सिग्नेचर को उजागर करते हैं, फिर connect एक ऑपरेशन स्टेट बनाता है और start इसे निष्पादित करता है। I/O और CPU विभिन्न शेड्यूलर्स का उपयोग करते हैं, जिनमें पैरेललिज्म, कतार और बैच सीमाएं होती हैं। रिसीवर वैल्यू, एरर और स्टॉप्ड को अलग-अलग संभालता है; प्रत्येक इंटरप्टिबल बिंदु स्टॉप टोकन की जाँच करता है। बाहरी राइट्स इडेम्पोटेंसी और कंपंसेशन सीमाओं का उपयोग करते हैं, इसलिए कैंसलेशन कभी भी रोलबैक का वादा नहीं करता है।
रिक्वेस्ट स्कोप पूरा होने तक ऑपरेशन स्टेट का स्वामी होता है, और एरर तथा स्टॉप्ड दोनों पाथ्स क्लीनअप साझा करते हैं। टूलचेन C++26 निष्पादन का पता लगाता है और मानक, एक कम्पैटिबिलिटी कार्यान्वयन, या सिंक्रोनस फ़ॉलबैक चुनता है। सभी पाथ्स खाली बैचों, रेस, कैंसलेशन प्रतिक्रिया, संसाधन थकावट और शुरुआती विनाश के लिए व्यवहार संबंधी परीक्षण साझा करते हैं। प्रोडक्शन में, मैं यह सत्यापित करने के लिए टेल लेटेंसी, कतार की गहराई, कैंसलेशन प्रतिक्रिया और लीक्स पर नज़र रखूँगा कि पैरेललिज्म लक्षित मीट्रिक में सुधार करता है या नहीं।
सामान्य गलतियाँ
- सेंडर निर्माण को एसिंक्रोनस कार्य शुरू करने के रूप में मानना।
- फ़ंक्शन के वापस आने पर ऑपरेशन स्टेट को नष्ट होने देना।
- केवल एक अपवाद चैनल का उपयोग करना और कैंसलेशन को एक सामान्य एरर के रूप में मानना।
- कतार, पैरेललिज्म या मेमोरी सीमाओं के बिना प्रति तत्व एक थ्रेड बनाना।
- यह दावा करना कि स्टॉप सिग्नल आने पर बाहरी साइड इफ़ेक्ट वापस रोल बैक हो गया था।
- पैरेलल एग्रीगेशन के लिए ऑर्डरिंग, फ़्लोटिंग-पॉइंट टॉलरेंस, या आंशिक-परिणाम नियमों को अपरिभाषित छोड़ना।
- कैपेबिलिटी डिटेक्शन या फ़ॉलबैक के बिना केवल एक स्टैंडर्ड-लाइब्रेरी पाथ को लागू करना।
फ़ॉलो-अप और प्रतिक्रियाएं
एक सेंडर वास्तव में कब चलता है?
कंपोज़िशन एक ग्राफ़ का वर्णन करता है। कनेक्ट करने से एक ऑपरेशन स्टेट बनता है, और start एसिंक्रोनस ऑपरेशन शुरू करता है। परीक्षणों में निर्माण, कनेक्शन और शुरुआत को अलग-अलग कवर किया जाना चाहिए।
क्या कोई स्टॉप अनुरोध किसी सिस्टम कॉल को जबरन समाप्त कर सकता है?
सामान्य तौर पर नहीं। कॉल को एक इंटरप्टिबल इंटरफ़ेस, एक टाइमआउट, या चंक्ड जांच की आवश्यकता होती है। अन्यथा यह लौटने के बाद प्रतिक्रिया देता है, और सबसे खराब प्रतिक्रिया समय को मापा जाना चाहिए।
क्या होगा यदि एरर और स्टॉप एक साथ होते हैं?
प्राथमिकता और एक एकल-कम्प्लीशन नियम को परिभाषित करें ताकि रिसीवर को ठीक एक टर्मिनल सिग्नल दिखाई दे। निदान के लिए मूल एरर और स्टॉप कारण दोनों को सुरक्षित रखें।
क्या होता है जब when_all की एक शाखा विफल हो जाती है?
निर्दिष्ट करें कि क्या अन्य शाखाएं जारी रहती हैं, स्टॉप अनुरोध प्राप्त करती हैं, या क्लीनअप समाप्त करती हैं। साझा संसाधनों को स्कोप्ड ओनरशिप और कैंसलेशन प्रोपेगेशन की आवश्यकता होती है; एग्रीगेटर को अमान्य शाखा परिणाम नहीं पढ़ना चाहिए।
आप एग्रीगेशन को पुनरुत्पादनीय (reproducible) कैसे बनाते हैं?
पार्टीशन सीक्वेंस नंबर बनाए रखें और एक निश्चित क्रम में मर्ज करें, या स्पष्ट रूप से एरर बाउंड के साथ अनऑर्डर्ड परिणामों की अनुमति दें। पैरेलल रिडक्शन फ़्लोटिंग-पॉइंट सहयोगीता (associativity) को मानकर नहीं चल सकता।
क्या होगा यदि प्रोडक्शन लाइब्रेरी में C++26 निष्पादन का अभाव हो?
कम्प्लीशन सेमेंटिक्स और परीक्षणों को संरक्षित करते हुए एक कम्पैटिबिलिटी कार्यान्वयन या सिंक्रोनस पाथ का चयन करने के लिए कंपाइलर कैपेबिलिटी मैट्रिक्स का उपयोग करें। सार्वजनिक इंटरफ़ेस में किसी प्रायोगिक लाइब्रेरी के निजी प्रकारों को उजागर न करें।