अंतर निष्पादन कैसे काम करता है?


83

मैंने स्टैक ओवरफ्लो पर इसके कुछ उल्लेख देखे हैं, लेकिन विकिपीडिया पर (संबंधित पेज तब से हटा दिया गया है) घूर कर और एक एमएफसी डायनेमिक डायलॉग डेमो पर मुझे ज्ञानवर्धन करने के लिए कुछ नहीं किया। क्या कोई इसे समझा सकता है? मौलिक रूप से भिन्न अवधारणा सीखना अच्छा लगता है।


उत्तरों के आधार पर: मुझे लगता है कि मैं इसके लिए बेहतर अनुभव प्राप्त कर रहा हूं। मुझे लगता है कि मैंने पहली बार स्रोत कोड को ध्यान से नहीं देखा। मुझे इस बिंदु पर अंतर निष्पादन के बारे में मिश्रित भावनाएं हैं। एक ओर, यह कुछ कार्यों को काफी आसान बना सकता है। दूसरी ओर, इसे उठना और चलाना (यानी, इसे अपनी पसंद की भाषा में सेट करना) आसान नहीं है (मुझे यकीन है कि अगर मैं इसे बेहतर समझ रहा हूं तो यह होगा) ... हालांकि मुझे लगता है कि इसके लिए टूलबॉक्स जरूरत केवल एक बार बनाई जाती है, फिर आवश्यकतानुसार विस्तारित की जाती है। मुझे लगता है कि वास्तव में इसे समझने के लिए, मुझे शायद इसे किसी अन्य भाषा में लागू करने की कोशिश करनी होगी।


3
आपकी रुचि के लिए धन्यवाद ब्रायन। मेरे लिए, यह दिलचस्प है कि कुछ सरल निराशाजनक लगता है। मेरे लिए, सबसे सुंदर चीजें सरल हैं। ख्याल रखना।
माइक डनलैवी

1
मुझे लगता है कि मुझे कुछ महत्वपूर्ण याद आ रहा है। अभी मैं सोच रहा हूं, "यह सरल है।" अगर मैं वास्तव में इसे समझता था, तो मुझे लगता है कि मैं सोच रहा हूँ, "यह सरल है। और वास्तव में अद्भुत और उपयोगी है।"
ब्रायन

6
... मैं अभी भी लोगों को एमवीसी को प्रस्तुत करते हुए देखता हूं जैसे कि यह सबसे बड़ी बात है, और मुझे लगता है कि मैं फिर से रिटायर होना चाहूंगा।
माइक डनलैवी

1
... "पूर्ववत करें" के लिए आप डेटा को क्रमबद्ध / डिस्क्रिअलाइज़ करते हैं, और एक फाइल को स्पिन करते हैं जो दो का XOR है, जो कि ज्यादातर शून्य है इसलिए आसानी से संपीड़ित होता है। पूर्व डेटा को पुनर्प्राप्त करने के लिए उपयोग करें। अब मनमानी डेटा संरचना के लिए सामान्यीकरण करें।
14

1
अपने वर्कलोड, @MikeDunlavey को जोड़ना नहीं चाहते हैं, लेकिन यदि आप इसे चूक गए हैं, तो स्रोत फोर्ज प्रश्नवाचक बिज़ प्रथाओं के साथ अनुग्रह से गिर गया। Github.com वह जगह है जहां आजकल शांत बच्चे लटके रहते हैं। वे पर W7 के लिए वास्तव में एक अच्छा Windows क्लाइंट है desktop.github.com
प्रो Falken

जवाबों:


95

जी, ब्रायन, काश मैं आपके प्रश्न को जल्द देख लेता। चूंकि यह मेरा "आविष्कार" (बेहतर या बदतर के लिए) बहुत है, इसलिए मैं मदद करने में सक्षम हो सकता हूं।

सम्मिलित: सबसे कम संभव व्याख्या जो मैं कर सकता हूं वह यह है कि यदि सामान्य निष्पादन हवा में गेंद फेंकने और उसे पकड़ने जैसा है, तो अंतर निष्पादन बाजीगरी की तरह है।

@ विंडफाइंडर की व्याख्या खान से अलग है, और यह ठीक है। इस तकनीक को किसी के सिर के चारों ओर लपेटना आसान नहीं है, और मुझे स्पष्टीकरण के लिए 20 साल (ऑफ और ऑन) लगे हैं ताकि स्पष्टीकरण मिल सके। मुझे इसे एक और शॉट यहाँ दें:

  • यह क्या है?

हम सभी एक कंप्यूटर के सरल विचार को एक प्रोग्राम के माध्यम से समझते हैं, जो इनपुट डेटा के आधार पर सशर्त शाखाएं लेते हैं, और चीजें करते हैं। (मान लें कि हम केवल सरल संरचित गोटो-कम, रिटर्न-कम कोड के साथ काम कर रहे हैं।) उस कोड में स्टेटमेंट्स, बेसिक स्ट्रक्चर्ड कंडीशन्स, सिंपल लूप्स और सबरूटीन कॉल्स के सीक्वेंस होते हैं। (अभी के लिए मान लौटाने वाले कार्यों के बारे में भूल जाएं।)

अब दो कंप्यूटरों को एक ही कोड को एक-दूसरे के साथ लॉक-स्टेप में निष्पादित करने की कल्पना करें, और नोटों की तुलना करने में सक्षम हों। कंप्यूटर 1 इनपुट डेटा ए के साथ चलता है, और कंप्यूटर 2 इनपुट डेटा बी के साथ चलता है। वे चरण-दर-चरण चलते हैं। यदि वे IF (परीक्षण) जैसे एक सशर्त विवरण में आते हैं .... ENDIF, और यदि उनके पास इस बात पर मतभेद है कि क्या परीक्षण सत्य है, तो वह जो परीक्षण कहता है कि यदि ENDIFIF गलत है और इसके लिए प्रतीक्षा करता है अपनी बहन को पकड़ने के लिए। (यही कारण है कि कोड संरचित है, इसलिए हमें पता है कि बहन अंततः ENDIF को मिल जाएगी।)

चूंकि दोनों कंप्यूटर एक-दूसरे से बात कर सकते हैं, वे नोटों की तुलना कर सकते हैं और इनपुट डेटा के दो सेट और निष्पादन हिस्टरी के बारे में विस्तृत विवरण दे सकते हैं।

बेशक, अंतर निष्पादन (डीई) में यह एक कंप्यूटर के साथ किया जाता है, दो का अनुकरण करता है।

अब, मान लीजिए कि आपके पास इनपुट डेटा का केवल एक सेट है, लेकिन आप यह देखना चाहते हैं कि यह समय-समय पर 1 से कैसे बदल गया है। मान लीजिए कि आप जिस प्रोग्राम को निष्पादित कर रहे हैं, वह एक धारावाहिक / डेज़राइज़र है। जैसा कि आप निष्पादित करते हैं, आप दोनों वर्तमान डेटा को लिखते हैं और पिछले डेटा (जो पिछली बार आपने ऐसा किया था लिखा था) में deserialize (पढ़ें)। अब आप आसानी से देख सकते हैं कि पिछली बार डेटा क्या था और इस समय क्या है, इसके बीच क्या अंतर हैं।

जिस फ़ाइल को आप लिख रहे हैं, और जिस पुरानी फ़ाइल से आप पढ़ रहे हैं, वह एक साथ ली गई एक कतार या FIFO (पहली-पहली-पहली-आउट) है, लेकिन यह बहुत गहरी अवधारणा नहीं है।

  • ये किस काम के लिए अच्छा है?

यह मेरे लिए तब हुआ जब मैं एक ग्राफिक्स प्रोजेक्ट पर काम कर रहा था, जहां उपयोगकर्ता "प्रतीकों" नामक छोटे डिस्प्ले-प्रोसेसर रूटीन का निर्माण कर सकता था, जिन्हें पाइप, टैंक, वाल्व, सामान जैसे आरेख जैसी चीजों को चित्रित करने के लिए बड़े रूटीन में इकट्ठा किया जा सकता था। हम चाहते थे कि आरेख "गतिशील" इस अर्थ में हो कि वे पूरे आरेख को फिर से खोले बिना अपने आप को अपडेट कर सकें। (हार्डवेयर आज के मानकों से धीमा था।) मैंने महसूस किया कि (उदाहरण के लिए) एक बार-चार्ट की एक पट्टी खींचने के लिए एक दिनचर्या अपनी पुरानी ऊंचाई को याद कर सकती है और बस खुद को अपडेट कर सकती है।

यह OOP की तरह लगता है, है ना? हालांकि, "बनाने" के बजाय एक "वस्तु", मैं आरेख प्रक्रिया के निष्पादन अनुक्रम की पूर्वानुमेयता का लाभ उठा सकता था। मैं एक अनुक्रमिक बाइट-स्ट्रीम में बार की ऊंचाई लिख सकता था। फिर छवि को अपडेट करने के लिए, मैं सिर्फ एक मोड में प्रक्रिया को चला सकता हूं जहां यह क्रमिक रूप से अपने पुराने मापदंडों को पढ़ता है जबकि यह नए मापदंडों को लिखता है ताकि अगले अपडेट पास के लिए तैयार रहें।

यह मूर्खतापूर्ण स्पष्ट लगता है और जैसे ही प्रक्रिया में एक सशर्त शामिल होता है, ऐसा लगता है, क्योंकि तब नई धारा और पुरानी धारा सिंक से बाहर हो जाएगी। लेकिन तब यह मुझ पर हावी हो गया कि अगर वे सशर्त परीक्षण के बूलियन मूल्य को क्रमबद्ध करते हैं, तो वे सिंक में वापस आ सकते हैं । खुद को समझाने में थोड़ा समय लगा और फिर यह साबित करने के लिए कि यह हमेशा काम करेगा , बशर्ते एक सरल नियम ("इरेज़ मोड रूल") का पालन किया जाए।

शुद्ध परिणाम यह है कि उपयोगकर्ता इन "गतिशील प्रतीकों" को डिजाइन कर सकता है और उन्हें बड़े आरेखों में इकट्ठा कर सकता है, कभी भी इस बारे में चिंता किए बिना कि वे गतिशील रूप से कैसे अपडेट करेंगे, चाहे वह कितना भी जटिल या संरचनात्मक रूप से परिवर्तनशील हो।

उन दिनों में, मुझे दृश्य वस्तुओं के बीच हस्तक्षेप के बारे में चिंता करने की ज़रूरत थी, ताकि किसी को मिटा देने से दूसरों को नुकसान न पहुंचे। हालांकि, अब मैं विंडोज कंट्रोल के साथ तकनीक का उपयोग करता हूं, और मैं विंडोज को मुद्दों को प्रस्तुत करने का ध्यान रखता हूं।

तो इससे क्या हासिल होता है? इसका मतलब है कि मैं नियंत्रणों को चित्रित करने के लिए एक प्रक्रिया लिखकर एक संवाद का निर्माण कर सकता हूं, और मुझे वास्तव में नियंत्रण वस्तुओं को याद रखने या उन्हें अपडेट करने से निपटने, या उन्हें प्रकट करने / गायब होने / शर्तों को वारंट के रूप में स्थानांतरित करने के बारे में चिंता करने की आवश्यकता नहीं है। परिणाम बहुत छोटा और सरल संवाद स्रोत कोड है, परिमाण के एक क्रम के बारे में, और गतिशील लेआउट जैसी चीजें या नियंत्रण की संख्या में परिवर्तन या सरणियों या नियंत्रणों के ग्रिड तुच्छ हैं। इसके अलावा, एक संपादन क्षेत्र जैसे नियंत्रण, संपादन डेटा के लिए तुच्छ रूप से बाध्य हो सकता है और यह हमेशा सही साबित होगा, और मुझे कभी भी इसकी घटनाओं से नहीं जूझना पड़ेगा। एक अनुप्रयोग स्ट्रिंग चर के लिए एक संपादन क्षेत्र में लाना एक-पंक्ति संपादित करना है।

  • यह समझना मुश्किल क्यों है?

मुझे समझाने के लिए सबसे कठिन जो मिला है वह यह है कि सॉफ्टवेयर के बारे में अलग तरह से सोचने की आवश्यकता है। प्रोग्रामर सॉफ्टवेयर के ऑब्जेक्ट-एक्शन दृश्य के प्रति इतनी दृढ़ता से वचनबद्ध हैं कि वे जानना चाहते हैं कि वस्तुएं क्या हैं, कक्षाएं क्या हैं, वे प्रदर्शन कैसे "निर्माण" करते हैं, और वे घटनाओं को कैसे संभालते हैं, कि यह एक चेरी लेता है उनमें से विस्फोट करने के लिए बम। मैं यह बताने की कोशिश करता हूं कि वास्तव में क्या मायने रखता है जो आपको कहने की जरूरत है?कल्पना कीजिए कि आप एक डोमेन-विशिष्ट भाषा (डीएसएल) का निर्माण कर रहे हैं, जहाँ आप सभी को यह करने की आवश्यकता है कि यह बताएं कि "मैं चर ए को यहाँ संपादित करना चाहता हूँ, चर बी को और वहाँ नीचे चर सी" और यह जादुई रूप से आपके लिए इसका ख्याल रखेगा। । उदाहरण के लिए, Win32 में संवादों को परिभाषित करने के लिए यह "संसाधन भाषा" है। यह पूरी तरह से अच्छा डीएसएल है, सिवाय इसके कि यह काफी दूर तक नहीं जाता है। यह मुख्य प्रक्रियात्मक भाषा में "जीवित" नहीं है, या आपके लिए घटनाओं को संभालता है, या इसमें लूप / सशर्त / सबरूटीन्स शामिल हैं। लेकिन इसका मतलब अच्छी तरह से है, और डायनामिक डायलॉग काम खत्म करने की कोशिश करता है।

तो, सोचने की अलग-अलग विधा है: किसी प्रोग्राम को लिखने के लिए, आप सबसे पहले एक उपयुक्त डीएसएल को खोजते हैं (या खोजते हैं), और अपने प्रोग्राम को जितना संभव हो उतना कोड करें। इसे उन सभी वस्तुओं और कार्यों से निपटने दें जो केवल कार्यान्वयन के लिए मौजूद हैं।

यदि आप वास्तव में अंतर निष्पादन को समझना चाहते हैं और इसका उपयोग करना चाहते हैं, तो कुछ मुश्किल मुद्दे हैं जो आपको यात्रा कर सकते हैं। मैंने एक बार इसे लिस्प मैक्रोज़ में कोडित किया था , जहां ये मुश्किल बिट्स आपके लिए संभाले जा सकते थे, लेकिन "सामान्य" भाषाओं में इसे नुकसान से बचने के लिए कुछ प्रोग्रामर अनुशासन की आवश्यकता होती है।

खेद है कि इतनी लंबी-चौड़ी हो गई। अगर मुझे समझ में नहीं आया है, अगर आप इसे इंगित करेंगे तो मैं इसकी सराहना करूंगा और मैं इसे ठीक करने की कोशिश कर सकता हूं।

जोड़ा गया:

में जावा घुमाओ , वहाँ एक उदाहरण कार्यक्रम TextInputDemo कहा जाता है। यह एक स्थिर संवाद है, जिसमें 270 लाइनें (50 राज्यों की सूची की गिनती नहीं) ले रही हैं। डायनामिक डायलॉग्स (MFC में) यह लगभग 60 लाइनें है:

#define NSTATE (sizeof(states)/sizeof(states[0]))
CString sStreet;
CString sCity;
int iState;
CString sZip;
CString sWholeAddress;

void SetAddress(){
    CString sTemp = states[iState];
    int len = sTemp.GetLength();
    sWholeAddress.Format("%s\r\n%s %s %s", sStreet, sCity, sTemp.Mid(len-3, 2), sZip);
}

void ClearAddress(){
    sWholeAddress = sStreet = sCity = sZip = "";
}

void CDDDemoDlg::deContentsTextInputDemo(){
    int gy0 = P(gy);
    P(www = Width()*2/3);
    deStartHorizontal();
    deStatic(100, 20, "Street Address:");
    deEdit(www - 100, 20, &sStreet);
    deEndHorizontal(20);
    deStartHorizontal();
    deStatic(100, 20, "City:");
    deEdit(www - 100, 20, &sCity);
    deEndHorizontal(20);
    deStartHorizontal();
    deStatic(100, 20, "State:");
    deStatic(www - 100 - 20 - 20, 20, states[iState]);
    if (deButton(20, 20, "<")){
        iState = (iState+NSTATE - 1) % NSTATE;
        DD_THROW;
    }
    if (deButton(20, 20, ">")){
        iState = (iState+NSTATE + 1) % NSTATE;
        DD_THROW;
    }
    deEndHorizontal(20);
    deStartHorizontal();
    deStatic(100, 20, "Zip:");
    deEdit(www - 100, 20, &sZip);
    deEndHorizontal(20);
    deStartHorizontal();
    P(gx += 100);
    if (deButton((www-100)/2, 20, "Set Address")){
        SetAddress();
        DD_THROW;
    }
    if (deButton((www-100)/2, 20, "Clear Address")){
        ClearAddress();
        DD_THROW;
    }
    deEndHorizontal(20);
    P((gx = www, gy = gy0));
    deStatic(P(Width() - gx), 20*5, (sWholeAddress != "" ? sWholeAddress : "No address set."));
}

जोड़ा गया:

कोड के लगभग 40 लाइनों में अस्पताल के मरीजों की एक सरणी को संपादित करने के लिए उदाहरण कोड है। लाइनें 1-6 "डेटाबेस" को परिभाषित करती हैं। लाइनें 10-23 यूआई की समग्र सामग्री को परिभाषित करती हैं। लाइनों 30-48 एक मरीज के रिकॉर्ड को संपादित करने के लिए नियंत्रण को परिभाषित करते हैं। ध्यान दें कि कार्यक्रम का रूप समय में घटनाओं की लगभग कोई सूचना नहीं है, जैसे कि यह सब करना था एक बार प्रदर्शन बनाएं। फिर, अगर विषयों को जोड़ा जाता है या हटा दिया जाता है या अन्य संरचनात्मक परिवर्तन होते हैं, तो इसे बस फिर से निष्पादित किया जाता है, जैसे कि इसे फिर से खरोंच से बनाया जा रहा है, सिवाय इसके कि डीईई वृद्धिशील अद्यतन के बजाय जगह लेता है। लाभ यह है कि आपको प्रोग्रामर को यूआई होने के वृद्धिशील अपडेट करने के लिए कोई ध्यान देने या कोई कोड लिखने की आवश्यकता नहीं है, और उन्हें सही गारंटी दी जाती है। यह लग सकता है कि यह पुन: निष्पादन एक प्रदर्शन समस्या होगी, लेकिन ऐसा नहीं है,

1  class Patient {public:
2    String name;
3    double age;
4    bool smoker; // smoker only relevant if age >= 50
5  };
6  vector< Patient* > patients;

10 void deContents(){ int i;
11   // First, have a label
12   deLabel(200, 20, “Patient name, age, smoker:”);
13   // For each patient, have a row of controls
14   FOR(i=0, i<patients.Count(), i++)
15     deEditOnePatient( P( patients[i] ) );
16   END
17   // Have a button to add a patient
18   if (deButton(50, 20, “Add”)){
19     // When the button is clicked add the patient
20     patients.Add(new Patient);
21     DD_THROW;
22   }
23 }

30 void deEditOnePatient(Patient* p){
31   // Determine field widths
32   int w = (Width()-50)/3;
33   // Controls are laid out horizontally
34   deStartHorizontal();
35     // Have a button to remove this patient
36     if (deButton(50, 20, “Remove”)){
37       patients.Remove(p);
37       DD_THROW;
39     }
40     // Edit fields for name and age
41     deEdit(w, 20, P(&p->name));
42     deEdit(w, 20, P(&p->age));
43     // If age >= 50 have a checkbox for smoker boolean
44     IF(p->age >= 50)
45       deCheckBox(w, 20, “Smoker?”, P(&p->smoker));
46     END
47   deEndHorizontal(20);
48 }

जोड़ा गया: ब्रायन ने एक अच्छा सवाल पूछा, और मुझे लगा कि इसका जवाब यहाँ के मुख्य पाठ में है:

@ माइक: मैं स्पष्ट नहीं हूँ कि क्या "अगर (डेबटन (50, 20," जोड़ें ")) {" कथन वास्तव में कर रहा है। डीबटन कार्य क्या करता है? इसके अलावा, क्या आपके मैक्रो या किसी चीज़ का उपयोग करने के लिए आपके फ़ोर / END लूप हैं? - ब्रायन

@ ब्रायन: हां, FOR / END और IF स्टेटमेंट्स मैक्रोज़ हैं। SourceForge परियोजना का पूर्ण कार्यान्वयन है। deButton एक बटन नियंत्रण रखता है। जब कोई भी उपयोगकर्ता इनपुट कार्रवाई करता है, तो कोड "कंट्रोल इवेंट" मोड में चलाया जाता है, जिसमें डीबटन यह पता लगाता है कि इसे दबाया गया था और यह दर्शाता है कि यह TRUE वापस करके दबाया गया था। इस प्रकार, "if (deButton (...)) {... एक्शन कोड ...} बटन का एक्शन कोड अटैच करने का एक तरीका है, बिना क्लोजर बनाए या ईवेंट हैंडलर लिखना। DD_THROW एक है। जब कार्रवाई की जाती है तो पास को समाप्त करने का तरीका क्योंकि कार्रवाई में संशोधित एप्लिकेशन डेटा हो सकता है, इसलिए रूटीन के माध्यम से "कंट्रोल इवेंट" को जारी रखना अमान्य है। यदि आप इसे लिखने वाले इवेंट हैंडलर से तुलना करते हैं, तो यह आपको उन लोगों को लिखने से बचाता है। और यह आपको किसी भी संख्या को नियंत्रित करने देता है।

जोड़ा गया: क्षमा करें, मुझे समझाना चाहिए कि "रखरखाव" शब्द से मेरा क्या मतलब है। जब प्रक्रिया को पहले (SHOW मोड में) निष्पादित किया जाता है, तो deButton एक बटन नियंत्रण बनाता है और FIFO में इसकी आईडी याद रखता है। बाद के पास (UPDATE मोड में) पर, डेबटन को FIFO से आईडी मिल जाती है, यदि आवश्यक हो तो इसे संशोधित करता है और इसे FIFO में वापस रख देता है। ERASE मोड में, यह इसे FIFO से पढ़ता है, इसे नष्ट कर देता है, और इसे वापस नहीं डालता है, जिससे इसे "कचरा एकत्रित करना" पड़ता है। इसलिए डेबटन कॉल पूरे जीवनकाल को नियंत्रण में रखता है, इसे एप्लिकेशन डेटा के साथ जोड़कर रखता है, यही कारण है कि मैं इसे "बनाए रखता हूं"।

चौथा मोड ईवेंट (या नियंत्रण) है। जब उपयोगकर्ता एक चरित्र टाइप करता है या एक बटन पर क्लिक करता है, तो उस घटना को पकड़ा जाता है और रिकॉर्ड किया जाता है, और फिर डिवॉन्टेंट्स प्रक्रिया को EVM मोड में निष्पादित किया जाता है। deButton को FIFO से अपने बटन नियंत्रण की आईडी मिलती है और पूछता है कि क्या यह नियंत्रण है जिसे क्लिक किया गया था। यदि ऐसा था, तो यह TRUE लौटाता है, इसलिए कार्रवाई कोड निष्पादित किया जा सकता है। यदि नहीं, तो यह केवल FALSE लौटाता है। दूसरी ओर, यह deEdit(..., &myStringVar)पता लगाता है कि क्या ईवेंट उसके लिए था, और यदि ऐसा है तो इसे एडिट कंट्रोल को पास करता है, और फिर एडिट कंट्रोल के कंटेंट को myStringVar पर कॉपी करता है। इस और सामान्य अद्यतन प्रसंस्करण के बीच, myStringVar हमेशा संपादन नियंत्रण की सामग्री के बराबर होता है। इस तरह "बंधन" किया जाता है। यही विचार स्क्रॉल बार, सूची बॉक्स, कॉम्बो बॉक्स, किसी भी प्रकार के नियंत्रण पर लागू होता है जो आपको एप्लिकेशन डेटा को संपादित करने देता है।

यहाँ मेरे विकिपीडिया संपादन का लिंक दिया गया है: http://en.wikipedia.org/wiki/User:MikeDunlavey/Difex_Article


4
और आपको जवाब के साथ प्लेग करने के लिए खेद है, लेकिन अगर मैं इसे सही ढंग से समझता हूं, तो आप मूल रूप से अपनी गणना को प्रोसेसर के करीब और आउटपुट हार्डवेयर से दूर ले जा रहे हैं। यह एक अविश्वसनीय अंतर्दृष्टि है क्योंकि हम इस विचार में बहुत सारे स्टॉक का निवेश करते हैं कि वस्तुओं और चर में प्रोग्रामिंग करके, वे एक ही आउटपुट प्राप्त करने के लिए सर्वश्रेष्ठ मशीन कोड में बहुत आसानी से अनुवादित होते हैं, जो निश्चित रूप से सभी मामलों में नहीं है! यद्यपि हम संकलन करते समय कोड का अनुकूलन कर सकते हैं, लेकिन समय-निर्भर कार्यों का अनुकूलन करना संभव नहीं है। समय पर निर्भरता से इंकार करें और काम करें !
सोवा

2
@ जोए: अब जब आप इसका उल्लेख करते हैं, तो एक नियंत्रण संरचना का विचार जो एक एफआईएफओ को चलाता है, और एक नौकरी कतार से समानांतर चलने वाली सह-दिनचर्या, वहां बहुत कुछ है।
माइक डनलैवी

2
मुझे आश्चर्य है कि रिएक्ट.जेएस लाइब्रेरी द्वारा उपयोग किए जाने वाले दृष्टिकोण के लिए विभेदक निष्पादन कितना करीब है।
ब्रायन

2
@ ब्रायन: जानकारी को स्किम करने से, react.js ब्राउज़र को वृद्धिशील अपडेट भेजने के लिए एक अलग फ़ंक्शन का उपयोग करता है। मैं बता नहीं सकता कि क्या अंतर फ़ंक्शन वास्तव में अंतर निष्पादन के रूप में सक्षम है। जैसे यह मनमाने बदलाव को संभाल सकता है, और यह बाध्यकारी को आसान बनाने का दावा करता है। क्या यह उसी डिग्री के लिए किया गया है जो मुझे नहीं पता। वैसे भी, मुझे लगता है कि यह सही रास्ते पर है। युगल वीडियो यहाँ।
माइक डनलैवी

2
@ माइकडूलेवी, मैं अपने टूल को ओपनजीएल / आईएमजीयूआई और मॉडल, मॉडल-व्यू और व्यू लेयर्स पर प्रतिक्रियात्मक प्रोग्रामिंग के संयोजन के साथ लिखता हूं। मैं अब पुरानी शैली में वापस नहीं जाऊंगा। आपके वीडियो के लिंक के लिए धन्यवाद।
Cthutu

13

विभेदक निष्पादन बाहरी घटनाओं के आधार पर आपके कोड के प्रवाह को बदलने के लिए एक रणनीति है। यह आमतौर पर परिवर्तनों को क्रॉनिकल करने के लिए किसी प्रकार की डेटा संरचना में हेरफेर करके किया जाता है। यह ज्यादातर ग्राफिकल यूजर इंटरफेस में उपयोग किया जाता है, लेकिन इसका उपयोग सीरियलाइजेशन जैसी चीजों के लिए भी किया जाता है, जहां आप एक मौजूदा "स्टेट" में बदलाव कर रहे हैं। "

मूल प्रवाह इस प्रकार है:

Start loop:
for each element in the datastructure: 
    if element has changed from oldDatastructure:
        copy element from datastructure to oldDatastructure
        execute corresponding subroutine (display the new button in your GUI, for example)
End loop:
Allow the states of the datastructure to change (such as having the user do some input in the GUI)

इसके फायदे कुछ ही हैं। एक, यह आपके परिवर्तनों के निष्पादन और सहायक डेटा के वास्तविक हेरफेर से अलग है। जो कई प्रोसेसर के लिए अच्छा है। दो, यह आपके कार्यक्रम में परिवर्तन संचार की एक कम बैंडविड्थ विधि प्रदान करता है।


12

मॉनिटर कैसे काम करता है इसके बारे में सोचो:

यह 60 हर्ट्ज पर अपडेट किया जाता है - एक सेकंड में 60 बार। झिलमिलाहट झिलमिलाहट झिलमिलाहट 60 बार, लेकिन आपकी आँखें धीमी हैं और वास्तव में नहीं बता सकती हैं। मॉनिटर दिखाता है कि आउटपुट बफर में जो कुछ भी है; यह सिर्फ इस डेटा को हर दूसरे के 1/60 वें हिस्से से बाहर निकाल देता है, चाहे आप कुछ भी करें।

अब आप अपने प्रोग्राम को पूरे बफर को 60 बार एक सेकंड में अपडेट करना चाहते हैं यदि छवि को अक्सर बदलना नहीं चाहिए? क्या होगा यदि आप केवल छवि के एक पिक्सेल को बदलते हैं, तो क्या आपको पूरे बफर को फिर से लिखना चाहिए?


यह मूल विचार का एक अमूर्त हिस्सा है: आप स्क्रीन पर प्रदर्शित की गई जानकारी के आधार पर आउटपुट बफर को बदलना चाहते हैं। आप जितना संभव हो उतना CPU समय और बफ़र लिखने के लिए समय बचाना चाहते हैं, इसलिए आप बफ़र के उन हिस्सों को संपादित नहीं करते जिन्हें अगले स्क्रीन पुल के लिए बदलने की आवश्यकता नहीं है।

मॉनिटर आपके कंप्यूटर और लॉजिक (प्रोग्राम्स) से अलग है। यह आउटपुट बफर से पढ़ता है जो भी स्क्रीन को अपडेट करता है। हम चाहते हैं कि हमारा कंप्यूटर सिंक्रोनाइज़ करना बंद कर दे और अनावश्यक रूप से लालच न दे। हम इसे बदलकर हल कर सकते हैं कि हम बफर के साथ कैसे काम करते हैं, जो विभिन्न तरीकों से किया जा सकता है। उनकी तकनीक एक एफआईएफओ कतार को लागू करती है जो देरी पर है - यह वही है जो हमने अभी बफर को भेजा है। विलंबित FIFO कतार में पिक्सेल डेटा नहीं होता है, यह "आकार प्रधानता" रखता है (जो आपके आवेदन में पिक्सेल हो सकता है, लेकिन यह भी लाइनें, आयताकार, आसान-से-आकर्षित चीजें हो सकती हैं क्योंकि वे सिर्फ आकार हैं, कोई अनावश्यक डेटा नहीं है अनुमति है)।

तो आप स्क्रीन से चीजों को खींचना / मिटा देना चाहते हैं? कोई दिक्कत नहीं है। फीफो कतार की सामग्री के आधार पर मुझे पता है कि मॉनिटर इस समय कैसा दिखता है। मैं FIFO कतार के साथ अपने वांछित आउटपुट (नए प्राइमेट को मिटाने या खींचने के लिए) की तुलना करता हूं और केवल उन मूल्यों को बदल देता हूं जिन्हें बदलने या अपडेट करने की आवश्यकता होती है। यह कदम है जो इसे विभेदक मूल्यांकन नाम देता है।

दो अलग-अलग तरीके जिनमें मैं इसकी सराहना करता हूं:

द फर्स्ट: माइक डनलवे एक सशर्त-स्टेटमेंट एक्सटेंशन का उपयोग करता है। FIFO कतार में बहुत सारी जानकारी होती है ("पिछली स्थिति" या मॉनिटर या समय-आधारित मतदान उपकरण पर वर्तमान सामान)। इसके लिए आपको बस इतना जोड़ना होगा कि आप अगले स्क्रीन पर दिखाई देना चाहते हैं।

हर स्लॉट में एक सशर्त बिट जोड़ा जाता है जो FIFO कतार में एक आदिम पकड़ सकता है।

0 means erase
1 means draw

हालाँकि, हमारे पास पिछली स्थिति है:

Was 0, now 0: don't do anything;
Was 0, now 1: add it to the buffer (draw it);
Was 1, now 1: don't do anything;
Was 1, now 0: erase it from the buffer (erase it from the screen);

यह सुरुचिपूर्ण है, क्योंकि जब आप कुछ अपडेट करते हैं, तो आपको वास्तव में केवल यह जानने की आवश्यकता होती है कि आप स्क्रीन पर कौन सी प्राइमेटिव्स आकर्षित करना चाहते हैं - यह तुलना यह पता लगाएगी कि क्या इसे एक आदिम को मिटा देना चाहिए या इसे बफर में जोड़ना / रखना चाहिए।

दूसरा: यह सिर्फ एक उदाहरण है, और मुझे लगता है कि माइक वास्तव में क्या प्राप्त कर रहा है, जो सभी परियोजनाओं के लिए डिजाइन में मौलिक होना चाहिए: अपने कम्प्यूटेशनल भोजन के रूप में अपने सबसे कम्प्यूटेशनल गहन कार्यों को लिखकर डिजाइन की जटिलता को कम करें। या जैसे ही आप प्राप्त कर सकते हैं। उपकरणों के प्राकृतिक समय का सम्मान करें।

संपूर्ण स्क्रीन को आकर्षित करने के लिए एक redraw विधि अविश्वसनीय रूप से महंगा है, और ऐसे अन्य अनुप्रयोग हैं जहां यह अंतर्दृष्टि अविश्वसनीय रूप से मूल्यवान है।

हम स्क्रीन के आसपास कभी भी "चलती" वस्तु नहीं हैं। यदि हम किसी कंप्यूटर मॉनीटर जैसी किसी चीज के लिए कोड डिजाइन करते हैं तो "मूविंग" एक महंगा ऑपरेशन है, जब हम "मूविंग" की शारीरिक क्रिया की नकल करने जा रहे हैं। इसके बजाय, ऑब्जेक्ट मूल रूप से मॉनीटर के साथ चालू और बंद होते हैं। हर बार जब कोई वस्तु चलती है, तो यह अब प्राइमेट का एक नया सेट है और प्राइमरी का पुराना सेट फ़्लिकर करता है।

हर बार मॉनिटर बफ़र से खींचता है हमारे पास ऐसी प्रविष्टियाँ हैं जो दिखती हैं

Draw bit    primitive_description
0           Rect(0,0,5,5);
1           Circ(0,0,2);
1           Line(0,1,2,5);

स्क्रीन (या समय-संवेदनशील पोलिंग डिवाइस) के साथ कोई ऑब्जेक्ट कभी भी इंटरैक्ट नहीं करता है। हम इसे एक वस्तु की तुलना में अधिक समझदारी से संभाल सकते हैं जब यह लालच से पूरी स्क्रीन को अपडेट करने के लिए कहता है केवल एक परिवर्तन को केवल अपने लिए विशिष्ट दिखाने के लिए।

कहो कि हमारे पास सभी संभावित चित्रमय प्राइमेट की एक सूची है जो हमारे कार्यक्रम को उत्पन्न करने में सक्षम है, और यह कि हम प्रत्येक आदिम को सशर्त बयानों के एक सेट से बाँधते हैं।

if (iWantGreenCircle && iWantBigCircle && iWantOutlineOnMyCircle) ...

बेशक, यह एक अमूर्तता है और, वास्तव में, सशर्त सेट जो एक विशेष आदिम का प्रतिनिधित्व करता है पर / बंद हो सकता है बड़े (शायद सैकड़ों झंडे हैं जो सभी को सही मूल्यांकन करना चाहिए)।

यदि हम कार्यक्रम चलाते हैं, तो हम स्क्रीन पर अनिवार्य रूप से उसी दर पर आकर्षित हो सकते हैं जिस पर हम इन सभी स्थितियों का मूल्यांकन कर सकते हैं। (सबसे खराब स्थिति: सशर्त बयानों के सबसे बड़े सेट का मूल्यांकन करने में कितना समय लगता है।)

अब, कार्यक्रम के किसी भी राज्य के लिए, हम बस स्क्रीन लाइटिंग-क्विक के लिए सभी शर्तों और आउटपुट का मूल्यांकन कर सकते हैं ! (हम अपने आकार आदिम और उनके आश्रित जानते हैं यदि कथन।)

यह एक ग्राफिक-इंटेंसिव गेम खरीदने जैसा होगा। केवल इसे अपने एचडीडी में स्थापित करने और अपने प्रोसेसर के माध्यम से चलाने के बजाय, आप एक ब्रांड-नया बोर्ड खरीदते हैं जो गेम की संपूर्णता को रखता है और इनपुट: माउस, कीबोर्ड और आउटपुट के रूप में लेता है: मॉनिटर। अविश्वसनीय रूप से गाढ़ा सशर्त मूल्यांकन (जैसा कि सशर्त का सबसे मौलिक रूप है सर्किट बोर्डों पर तर्क द्वार)। यह, स्वाभाविक रूप से, बहुत संवेदनशील होगा, लेकिन यह बग को ठीक करने में लगभग कोई समर्थन नहीं प्रदान करता है, क्योंकि जब आप एक छोटे से डिज़ाइन में बदलाव करते हैं तो पूरा बोर्ड डिज़ाइन बदलता है (क्योंकि "डिज़ाइन" सर्किट बोर्ड की प्रकृति से बहुत दूर है। )। लचीलेपन और स्पष्टता की कीमत पर हम आंतरिक रूप से डेटा का प्रतिनिधित्व करते हैं हमने महत्वपूर्ण "जवाबदेही" प्राप्त की है क्योंकि हम अब कंप्यूटर में "सोच" नहीं रहे हैं; इनपुट के आधार पर सर्किट बोर्ड के लिए।

सबक, जैसा कि मैं इसे समझता हूं, श्रम को विभाजित करना है जैसे कि आप सिस्टम के प्रत्येक भाग को देते हैं (जरूरी नहीं कि सिर्फ कंप्यूटर और मॉनिटर) कुछ ऐसा कर सकता है जो अच्छा कर सकता है। "कंप्यूटर सोच" वस्तुओं की तरह अवधारणाओं के संदर्भ में किया जा सकता है ... कंप्यूटर मस्तिष्क ख़ुशी से आपके लिए यह सब करने की कोशिश करेगा और सोच सकता है, लेकिन यदि आप कंप्यूटर को सोचने देने में सक्षम हैं तो आप इस कार्य को सरल बना सकते हैं। data_update और conditional_evals की शर्तें। कोड में अवधारणाओं के बारे में हमारी मानवीय अमूर्तता आदर्शवादी है, और आंतरिक कार्यक्रम के मामले में कुछ हद तक आदर्शवादी तरीके हैं। जब आप चाहते हैं एक परिणाम (सही रंग मूल्यों के साथ पिक्सल के सरणी) और आप एक मशीन है कि आसानी से कर सकते हैं उस सरणी को थूक दें जो सेकंड के 1/60 वें हिस्से में बड़ा हो, कंप्यूटर मस्तिष्क से जितना संभव हो सके उतनी फूलदार सोच को खत्म करने की कोशिश करें ताकि आप इस बात पर ध्यान केंद्रित कर सकें कि आप वास्तव में क्या चाहते हैं: अपने (तेज़) इनपुट्स के साथ अपने ग्राफिकल अपडेट को सिंक्रनाइज़ करने के लिए मॉनिटर का प्राकृतिक व्यवहार।

यह मानचित्र अन्य अनुप्रयोगों के लिए कैसा है? मैं अन्य उदाहरणों के बारे में सुनना चाहूंगा, लेकिन मुझे यकीन है कि कई हैं। मुझे लगता है कि कुछ भी जो आपकी जानकारी की स्थिति में एक वास्तविक समय "विंडो" प्रदान करता है (चर राज्य या डेटाबेस की तरह कुछ ... एक मॉनिटर सिर्फ आपके प्रदर्शन बफर में एक खिड़की है) इन अंतर्दृष्टि से लाभ उठा सकते हैं।


2
++ मैं इस पर अपने ले की सराहना करते हैं। मेरे लिए, शुरू में यह धीमी डिवाइसों पर प्रोग्राम-वर्णित डिस्प्ले करने का प्रयास था (9600-बॉड रिमोट टेक्स्ट टर्मिनलों के बारे में सोचें), जहां यह मूल रूप से एक स्वचालित अंतर करेगा और न्यूनतम अपडेट प्रसारित करेगा। फिर मुझे इस बात पर दबाया गया कि क्यों न इसे केवल क्रूर बल द्वारा कोड किया जाए। उत्तर: क्योंकि यदि कोड की सतह का रूप ऐसा है जैसे कि यह एक साधारण पेंट है , यह छोटा है, लगभग बग-कम है, इसलिए इसे विकास के समय के एक अंश में किया जाता है। (यही मैं एक डीएसएल के लाभ के रूप में सोचता हूं।)
माइक डनलैवी

... जिस विकास प्रयास को मुक्त किया जाता है, उसे फिर से अधिक परिष्कृत और गतिशील प्रदर्शनों में फिर से निवेश किया जा सकता है, जो उपयोगकर्ताओं को उत्तरदायी और मनभावन लगता है। इसलिए आपको डेवलपर हिरन के लिए और अधिक यूआई बैंग मिलते हैं।
माइक डनलैवी

... उदाहरण: लगभग 10 साल पहले का यह ऐप: pharsight.com/products/prod_pts_using_dme.php
माइक डनलैवी

1
यह मुझे समझ में आया ... जब आपने कंप्यूटर गेम के बारे में बात की थी। दरअसल, कई गेम को कोड किया जाता है जैसे कि माइक यूजर इंटरफेस कैसे करता है। एक अद्यतन सूची जो हर फ्रेम के साथ साइकिल से जाती है।
प्रो। फल्केन

आपने जो कहा उसमें से कुछ के लिए एक उचित रूप से संबंधित उदाहरण यह पता लगा रहा है कि क्या कुंजी / बटन नीचे रखा जा रहा है, या बस जारी किया गया था। यह जानना आसान है कि कोई बटन दबाया गया है या नहीं। यह आपके निम्न स्तर के एपीआई से एक सही / गलत मूल्य है। यह जानने के लिए कि क्या कोई कुंजी नीचे रखी जा रही है, आपको यह जानना होगा कि यह किस अवस्था में था। यदि यह 0-> 1 से है तो इसे बस दबाया जाता है। यदि यह 1-> 1 है तो इसे नीचे रखा जा रहा है, यदि यह 1-> 0 से है तो आपने अभी जारी किया है।
यहोशू

3

मुझे यह अवधारणा क्लासिक डिजिटल इलेक्ट्रॉनिक्स की राज्य मशीनों के समान लगती है। विशेष रूप से जो अपने पिछले आउटपुट को याद करते हैं।

एक मशीन जिसका अगला आउटपुट मौजूदा इनपुट और पिछले आउटपुट पर निर्भर करता है (आपका कोड यहाँ)। यह वर्तमान इनपुट कुछ और नहीं बल्कि पिछले आउटपुट + (USER, INTERACT HERE) है।

ऐसी मशीनों के साथ एक सतह को भरें, और यह उपयोगकर्ता इंटरैक्टिव होगा और एक ही समय में परिवर्तनशील डेटा की एक परत का प्रतिनिधित्व करेगा। लेकिन इस स्तर पर यह अभी भी गूंगा होगा, बस अंतर्निहित डेटा के लिए उपयोगकर्ता इंटरैक्शन को प्रतिबिंबित करेगा।

इसके बाद, अपनी सतह पर मशीनों को इंटरकनेक्ट करें, उन्हें (आपके कोड यहाँ) के अनुसार नोट्स साझा करने दें, और अब हम इसे बुद्धिमान बनाते हैं। यह एक इंटरेक्टिव कंप्यूटिंग सिस्टम बन जाएगा।

इसलिए आपको उपरोक्त मॉडल में दो स्थानों पर अपना तर्क देना होगा; बाकी की देखभाल मशीन की डिज़ाइन द्वारा की जाती है। यही इसके बारे में अच्छा है।


1
मुझे याद है कि मेरे दिमाग में एक हार्डवेयर मॉडल था जब मेरे साथ ऐसा हुआ था।
माइक डनलैवी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.