स्पिनलॉक: Difference between revisions

From Vigyanwiki
No edit summary
No edit summary
Line 9: Line 9:
स्पिनलॉक को लागू करने के लिए निम्न उदाहरण x86 असेंबली भाषा का उपयोग करता है। यह किसी भी इंटेल [[80386]] अनुरूप प्रोसेसर पर काम करेगा।
स्पिनलॉक को लागू करने के लिए निम्न उदाहरण x86 असेंबली भाषा का उपयोग करता है। यह किसी भी इंटेल [[80386]] अनुरूप प्रोसेसर पर काम करेगा।
<वाक्यविन्यास प्रकाश लैंग = एनएएसएम>
<वाक्यविन्यास प्रकाश लैंग = एनएएसएम>
; इंटेल सिंटैक्स


बंद:; ताला चर। 1 = लॉक, 0 = अनलॉक।
<nowiki>;</nowiki> Intel syntax                                                                locked<nowiki>:</nowiki>                      ; The lock variable. 1 = locked, 0 = unlocked.
     डीडी 0
dd     0


स्पिन_लॉक
spin_lock:
    मूव ईएक्स, 1;ईएक्स रजिस्टर को 1 पर सेट करें।
mov    eax, 1         ; Set the EAX register to 1.
    एक्ससीजी ईएक्स, [लॉक];ईएक्स रजिस्टर को परमाणु रूप से स्वैप करें
xchg    eax, [locked]   ; Atomically swap the EAX register with
                            ; ताला चर।
<nowiki/>; the lock variable.
                            ; यह हमेशा 1 को लॉक करने के लिए स्टोर करेगा
<nowiki/>; This will always store 1 to the lock, leaving
                            ;ईएक्स रजिस्टर में पिछला मान।
<nowiki/>; the previous value in the EAX register.
    टेस्ट ईएक्स, ईएक्स;ईएक्स को स्वयं के साथ टेस्ट करें। अन्य बातों के अतिरिक्त, यह होगा
test    eax, eax        ; Test EAX with itself. Among other things, this will
                            ; यदि भी बंद कर दिया है।
<nowiki/>;  set the processor's Zero Flag if EAX is 0.
                            ; अन्यथा, ईएक्स 1 है और हमने लॉक हासिल नहीं किया है।
<nowiki/>; If EAX is 0, then the lock was unlocked and
    जेएनजेड स्पिन_लॉक; यदि जीरो फ्लैग है तो MOV निर्देश पर वापस जाएं
<nowiki/>; we just locked it.
                            ; सेट नहीं; ताला पहले बंद था, और इसलिए
<nowiki/>; Otherwise, EAX is 1 and we didn't acquire the lock.
                            ; हमें तब तक स्पिन करने की जरूरत है जब तक कि यह अनलॉक न हो जाए।
jnz    spin_lock      ; Jump back to the MOV instruction if the Zero Flag is
    रिट; लॉक प्राप्त कर लिया गया है, कॉलिंग पर वापस लौटें
<nowiki/>; not set; the lock was previously locked, and so
                            ; समारोह।
<nowiki/>; we need to spin until it becomes unlocked.
ret                    ; The lock has been acquired, return to the calling
<nowiki/>; function.


स्पिन अनलॉक    एक्सोर ईएक्स, ईएक्स;ईएक्स रजिस्टर को 0 पर सेट करें।
spin_unlock:
एक्ससीजी ईएक्स, [लॉक];ईएक्स रजिस्टर को परमाणु रूप से स्वैप करें
xor    eax, eax        ; Set the EAX register to 0.
<nowiki>;</nowiki> ताला चर।
xchg    eax, [locked]   ; Atomically swap the EAX register with
रिट; ताला प्रकाशित हो चुकी है।.
<nowiki/>; the lock variable.
 
ret                    ; The lock has been released.
</वाक्यविन्यास हाइलाइट>


== महत्वपूर्ण अनुकूलन ==
== महत्वपूर्ण अनुकूलन ==
Line 48: Line 48:
<वाक्यविन्यास प्रकाश लैंग = एनएएसएम>
<वाक्यविन्यास प्रकाश लैंग = एनएएसएम>
; सी में: जबकि (!
; सी में: जबकि (!
स्पिन_लॉक:
 
     मूव ईसीएक्स, 1; ईसीएक्स रजिस्टर को 1 पर सेट करें।
  spin_lock:
पुन: प्रयास करें:
 
     एक्सोर ईएक्स, ईएक्स;ईएक्स को ज़ीरो आउट करें, क्योंकि cmpxchgईएक्स से तुलना करता है।
    mov     ecx, 1             ; Set the ECX register to 1.
    XACQUIRE लॉक cmpxchg [लॉक],उन्नत सिनेमा अनुभव) प्रौद्योगिकी।
retry:
                              ; परमाणु रूप से निर्णय लें: यदि लॉक शून्य है, तो इसे ईसीएक्स लिखें।
xor     eax, eax          ; Zero out EAX, because cmpxchg compares against EAX.
                              ; XACQUIRE प्रोसेसर को संकेत देता है कि हम एक लॉक प्राप्त कर रहे हैं।
XACQUIRE lock cmpxchg [locked], ecx
    जेई आउट; यदि हमने इसे लॉक कर दिया है (पुराना मानईएक्स: 0 के बराबर है), तो वापस लौटें।
<nowiki/>; atomically decide: if locked is zero, write ECX to it.
<nowiki/>; XACQUIRE hints to the processor that we are acquiring a lock.
je      out                ; If we locked it (old value equal to EAX: 0), return.
रोकना:
रोकना:
    मूव ईएक्स, [लॉक]; ईएक्स में बंद पढ़ें।
मूव ईएक्स, [लॉक]; ईएक्स में बंद पढ़ें।
     टेस्ट ईएक्स, ईएक्स; पहले की तरह शून्य-परीक्षण करें।
     टेस्ट ईएक्स, ईएक्स; पहले की त  रह शून्य-परीक्षण करें।
     जे जेड पुनः प्रयास करें; यदि यह शून्य है, तो हम पुनः प्रयास कर सकते हैं।
     जे जेड पुनः प्रयास करें; यदि यह शून्य है, तो हम पुनः प्रयास कर सकते हैं।
     प्रतिनिधि नोप; सीपीयू को बताएं कि हम स्पिनलूप में इंतजार कर रहे हैं, तो यह हो सकता है
     प्रतिनिधि नोप; सीपीयू को बताएं कि हम स्पिनलूप में इंतजार कर रहे हैं, तो यह हो सकता है
Line 66: Line 69:
     रिट; सब कुछ कर दिया।
     रिट; सब कुछ कर दिया।


स्पिन अनलॉक
  spin_unlock:
    XRELEASE मूव [लॉक], 0; मान लें कि मेमोरी ऑर्डरिंग नियम लागू होते हैं, तो रिलीज़ करें
 
                              ; लॉक रिलीज़ हिंट के साथ लॉक वेरिएबल।
    XRELEASE mov [locked], 0   ; Assuming the memory ordering rules apply, release the
    रिट; ताला प्रकाशित हो चुकी है।.
                                ; lock variable with a "lock release" hint.
    ret                        ; The lock has been released.
</वाक्यविन्यास हाइलाइट>
</वाक्यविन्यास हाइलाइट>



Revision as of 10:44, 25 December 2022

सॉफ्टवेयर इंजीनियरिंग में, एक स्पिनलॉक एक लॉक (कंप्यूटर साइंस) है जो एक थ्रेड (कंप्यूटर साइंस) का कारण बनता है जो बार-बार जांच कर रहा है कि लॉक उपलब्ध है या नहीं। चूँकि थ्रेड सक्रिय रहता है लेकिन कोई उपयोगी कार्य नहीं कर रहा है, ऐसे लॉक का उपयोग एक प्रकार का व्यस्त प्रतीक्षा है। एक बार अधिग्रहित होने के बाद, स्पिनलॉक सामान्यतः तब तक आयोजित किए जाते हैं जब तक कि वे स्पष्ट रूप से जारी नहीं हो जाते हैं, चूंकि कुछ कार्यान्वयनों में वे स्वचालित रूप से जारी हो सकते हैं यदि थ्रेड पर प्रतीक्षा की जा रही है (जिस पर ताला लगा है) ब्लॉक हो जाता है या सो जाता है।

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

स्पिनलॉक्स को सही ढंग से कार्यान्वित करना चुनौतीपूर्ण है क्योंकि प्रोग्रामर को लॉक तक एक साथ पहुंच की संभावना को ध्यान में रखना चाहिए, जो दौड़ की स्थिति पैदा कर सकता है। सामान्यतः, ऐसा कार्यान्वयन केवल विशेष सभा की भाषा | असेंबली-लैंग्वेज निर्देशों के साथ ही संभव है, जैसे परमाणु संचालन परीक्षण और सेट संचालन और प्रोग्रामिंग भाषाओं में आसानी से लागू नहीं किया जा सकता है जो वास्तव में परमाणु संचालन का समर्थन नहीं करते हैं।[1] इस तरह के संचालन के बिना आर्किटेक्चर पर, या यदि उच्च स्तरीय भाषा कार्यान्वयन की आवश्यकता होती है, तो गैर-परमाणु लॉकिंग एल्गोरिदम का उपयोग किया जा सकता है, उदाहरण के लिए पीटरसन का एल्गोरिदम। चूंकि, इस तरह के कार्यान्वयन के लिए स्पिनलॉक की तुलना में अधिक स्मृति की आवश्यकता हो सकती है, अनलॉक करने के बाद प्रगति की अनुमति देने के लिए धीमी हो, और उच्च-स्तरीय भाषा में कार्यान्वयन योग्य न हो, यदि आउट-ऑफ-ऑर्डर निष्पादन की अनुमति है।

उदाहरण कार्यान्वयन

स्पिनलॉक को लागू करने के लिए निम्न उदाहरण x86 असेंबली भाषा का उपयोग करता है। यह किसी भी इंटेल 80386 अनुरूप प्रोसेसर पर काम करेगा। <वाक्यविन्यास प्रकाश लैंग = एनएएसएम>

; Intel syntax locked:  ; The lock variable. 1 = locked, 0 = unlocked. dd 0

spin_lock: mov eax, 1  ; Set the EAX register to 1. xchg eax, [locked]  ; Atomically swap the EAX register with ; the lock variable. ; This will always store 1 to the lock, leaving ; the previous value in the EAX register. test eax, eax  ; Test EAX with itself. Among other things, this will ; set the processor's Zero Flag if EAX is 0. ; If EAX is 0, then the lock was unlocked and ; we just locked it. ; Otherwise, EAX is 1 and we didn't acquire the lock. jnz spin_lock  ; Jump back to the MOV instruction if the Zero Flag is ; not set; the lock was previously locked, and so ; we need to spin until it becomes unlocked. ret  ; The lock has been acquired, return to the calling ; function.

spin_unlock: xor eax, eax  ; Set the EAX register to 0. xchg eax, [locked]  ; Atomically swap the EAX register with ; the lock variable. ret  ; The lock has been released.

महत्वपूर्ण अनुकूलन

उपरोक्त सरल कार्यान्वयन x86 आर्किटेक्चर का उपयोग कर सभी सेंट्रल प्रोसेसिंग यूनिट पर काम करता है। चूंकि, कई प्रदर्शन अनुकूलन संभव हैं:

x86 आर्किटेक्चर के बाद के कार्यान्वयन पर, स्पिन अनलॉक धीरे-धीरे लॉक किए गए एक्ससीएचजी के अतिरिक्त अनलॉक किए गए एमओवी का सुरक्षित रूप से उपयोग कर सकता है। यह सूक्ष्म मेमोरी ऑर्डरिंग नियमों के कारण है जो इसका समर्थन करते हैं, ? एमओवी पूर्ण मेमोरी बैरियर नहीं है। चूंकि, कुछ प्रोसेसर (कुछ सिरिक्स प्रोसेसर, ? पेंटियम प्रो के कुछ संशोधन (बग के कारण), और पहले के पेंटियम (ब्रांड) और i486 सममित मल्टीप्रोसेसिंग सिस्टम) गलत काम करेंगे और लॉक द्वारा संरक्षित डेटा दूषित हो सकता है। अधिकांश गैर-x86 आर्किटेक्चर पर, स्पष्ट स्मृति बाधा या परमाणु निर्देश (उदाहरण के अनुसार) का उपयोग किया जाना चाहिए। कुछ प्रणालियों पर, जैसे IA-64, विशेष अनलॉक निर्देश हैं जो आवश्यक मेमोरी क्रम प्रदान करते हैं।

इंटर-सीपीयू बस (कंप्यूटिंग) को कम करने के लिए, लॉक प्राप्त करने का प्रयास करने वाले कोड को कुछ भी लिखने की कोशिश किए बिना पढ़ने को लूप करना चाहिए जब तक कि यह एक परिवर्तित मान नहीं पढ़ता। MESI कैशिंग प्रोटोकॉल के कारण, यह कैश लाइन को लॉक के लिए साझा करने का कारण बनता है; तब उल्लेखनीय रूप से कोई बस यातायात नहीं होता है जबकि सीपीयू लॉक की प्रतीक्षा करता है। यह ऑप्टिमाइज़ेशन उन सभी सेंट्रल प्रोसेसिंग यूनिट आर्किटेक्चर पर प्रभावी है जिनके पास प्रति सेंट्रल प्रोसेसिंग यूनिट कैश है, क्योंकि एमईएसआई इतना व्यापक है। हाइपर-थ्रेडिंग सीपीयू पर, के साथ रुकना repnop कोर को संकेत देकर अतिरिक्त प्रदर्शन देता है कि यह दूसरे थ्रेड पर काम कर सकता है जबकि लॉक स्पिन प्रतीक्षा कर रहा है।[2] लेन-देन तुल्यकालन एक्सटेंशन और अन्य हार्डवेयर लेन-देन स्मृति इंस्ट्रक्शन सेट ज्यादातर मामलों में लॉक को बदलने के लिए काम करते हैं। चूंकि लॉकबैक के रूप में अभी भी ताले की आवश्यकता है, लेकिन उनके पास प्रोसेसर को परमाणु संचालन के पूरे ब्लॉक को संभालने के द्वारा प्रदर्शन में काफी सुधार करने की क्षमता है। यह सुविधा कुछ म्यूटेक्स कार्यान्वयनों में अंतर्निहित है, उदाहरण के लिए glibc में। X86 में हार्डवेयर लॉक एलिसन (उच्च परत इकाई) ट्रांसमिसिबल स्पॉन्गॉर्मॉर्म एन्सेफैलोपैथी का एक कमजोर लेकिन पीछे की ओर अनुरूप संस्करण है, और हम इसे बिना किसी अनुकूलता खोए लॉकिंग के लिए यहां उपयोग कर सकते हैं। इस विशेष मामले में, प्रोसेसर तब तक लॉक नहीं करना चुन सकता है जब तक कि दो धागे वास्तव में एक दूसरे के साथ संघर्ष न करें।[3] परीक्षण का एक सरल संस्करण उपयोग कर सकता है cmpxchg x86 पर निर्देश, या __sync_bool_compare_and_swap कई यूनिक्स कंपाइलर्स में निर्मित।

लागू किए गए ऑप्टिमाइज़ेशन के साथ, एक नमूना ऐसा दिखाई देगा: <वाक्यविन्यास प्रकाश लैंग = एनएएसएम>

सी में
जबकि (!
  spin_lock:
    mov     ecx, 1             ; Set the ECX register to 1.

retry: xor eax, eax  ; Zero out EAX, because cmpxchg compares against EAX. XACQUIRE lock cmpxchg [locked], ecx ; atomically decide: if locked is zero, write ECX to it. ; XACQUIRE hints to the processor that we are acquiring a lock. je out  ; If we locked it (old value equal to EAX: 0), return.

रोकना:

मूव ईएक्स, [लॉक]; ईएक्स में बंद पढ़ें।
   टेस्ट ईएक्स, ईएक्स; पहले की त   रह शून्य-परीक्षण करें।
   जे जेड पुनः प्रयास करें; यदि यह शून्य है, तो हम पुनः प्रयास कर सकते हैं।
   प्रतिनिधि नोप; सीपीयू को बताएं कि हम स्पिनलूप में इंतजार कर रहे हैं, तो यह हो सकता है
                              ; अब दूसरे धागे पर काम करो। विराम के रूप में भी लिखा गया है।
   जेएमपी विराम; चेक-पॉज़ करते रहें।

बाहर:

   रिट; सब कुछ कर दिया।
  spin_unlock:
    XRELEASE mov [locked], 0   ; Assuming the memory ordering rules apply, release the 
                               ;  lock variable with a "lock release" hint.
    ret                        ; The lock has been released.

</वाक्यविन्यास हाइलाइट>

संशोधित अनन्य साझा और अमान्य प्रोटोकॉल का उपयोग करने वाले किसी भी बहु-प्रोसेसर सिस्टम पर, ऐसा टेस्ट-एंड-टेस्ट-एंड-सेट लॉक (टीटीएएस) सरल टेस्ट-एंड-सेट लॉक (टीएएस) दृष्टिकोण से काफी बेहतर प्रदर्शन करता है।[4] बड़ी संख्या में प्रोसेसर के साथ, लॉक को फिर से जांचने से पहले रैंडम घातीय बैकऑफ़ देरी जोड़ना विश्वसनीय टोकन प्रमाणीकरण सेवा से भी बेहतर प्रदर्शन करता है।[4][5] कुछ मल्टी-कोर प्रोसेसर में एक शक्ति-सचेत स्पिन-लॉक निर्देश होता है जो प्रोसेसर को सोने के लिए रखता है, फिर लॉक मुक्त होने के बाद अगले चक्र पर इसे जगाता है। इस तरह के निर्देशों का उपयोग करने वाला एक स्पिन-लॉक अधिक कुशल है और बैक-ऑफ लूप के साथ या उसके बिना स्पिन लॉक की तुलना में कम ऊर्जा का उपयोग करता है।[6]


विकल्प

स्पिनलॉक का प्राथमिक हानि यह है कि लॉक प्राप्त करने के लिए प्रतीक्षा (ऑपरेटिंग सिस्टम) करते समय, यह उस समय को तबाह करता है जो उत्पादक रूप से कहीं और खर्च किया जा सकता है। इससे बचने के दो तरीके हैं:

  1. लॉक हासिल न करें। कई स्थितियों में डेटा संरचनाओं को डिजाइन करना संभव है जो गैर-अवरुद्ध सिंक्रनाइज़ेशन, उदा। प्रति-थ्रेड या प्रति-सेंट्रल प्रोसेसिंग यूनिट डेटा का उपयोग करके और व्यवधानों को अक्षम करके।
  2. प्रतीक्षा करते समय संदर्भ एक अलग थ्रेड पर स्विच करें। इसमें सामान्यतः वर्तमान थ्रेड को लॉक की प्रतीक्षा कर रहे थ्रेड्स की कतार में संलग्न करना सम्मिलित है, इसके बाद किसी अन्य थ्रेड पर स्विच करना जो कुछ उपयोगी कार्य करने के लिए तैयार है। इस योजना का लाभ यह भी है कि यह गारंटी देता है कि संसाधनों की भुखमरी तब तक नहीं होती है जब तक कि सभी धागे अंततः उन ताले को छोड़ देते हैं जो वे प्राप्त करते हैं और शेड्यूलिंग निर्णय किए जा सकते हैं कि किस धागे को पहले प्रगति करनी चाहिए। स्पिनलॉक जो कभी भी स्विचिंग की आवश्यकता नहीं होती है, रीयल-टाइम ऑपरेटिंग सिस्टम द्वारा प्रयोग करने योग्य होती है। रीयल-टाइम ऑपरेटिंग सिस्टम, कभी-कभी कच्चे स्पिनलॉक्स कहलाते हैं।[7]

अधिकांश ऑपरेटिंग सिस्टम (सोलारिस (ऑपरेटिंग सिस्टम), Mac OS X और फ्रीबीएसडी सहित) एडाप्टिव आपसी बहिष्कार नामक हाइब्रिड दृष्टिकोण का उपयोग करते हैं। वर्तमान में चल रहे थ्रेड द्वारा लॉक किए गए संसाधन तक पहुँचने का प्रयास करते समय स्पिनलॉक का उपयोग करने का विचार है, लेकिन यदि थ्रेड (कंप्यूटिंग) वर्तमान में नहीं चल रहा है तो सोने के लिए। (बाद वाला हमेशा सिंगल-प्रोसेसर सिस्टम पर होता है।)[8] OpenBSD ने स्पिनलॉक्स को टिकट ताला से बदलने का प्रयास किया, जिसने फीफो (कंप्यूटिंग और इलेक्ट्रॉनिक्स) को लागू किया। पहले-में-पहले-बाहर व्यवहार, चूंकि इसके परिणामस्वरूप कर्नेल में अधिक सेंट्रल प्रोसेसिंग यूनिटउपयोग हुआ और फ़ायर्फ़ॉक्स जैसे बड़े अनुप्रयोग, बहुत धीमे हो गए।[9][10]


यह भी देखें

संदर्भ

  1. Silberschatz, Abraham; Galvin, Peter B. (1994). ऑपरेटिंग सिस्टम अवधारणाओं (Fourth ed.). Addison-Wesley. pp. 176–179. ISBN 0-201-59292-4.
  2. "जीसीसी - x86 spinlock cmpxchg का उपयोग कर". Stack Overflow.
  3. "आर्म आर्किटेक्चर में नई तकनीकें" (PDF). Archived (PDF) from the original on 2019-04-02. Retrieved 2019-09-26.
  4. 4.0 4.1 Maurice Herlihy and Nir Shavit. "The Art of Multiprocessor Programming". "Spin Locks and Contention".
  5. "Boost.Fiber Tuning: Exponential back-off".
  6. John Goodacre and Andrew N. Sloss. "Parallelism and the ARM Instruction Set Architecture". p. 47.
  7. Jonathan Corbet (9 December 2009). "स्पिनलॉक नामकरण का समाधान किया गया". LWN.net. Archived from the original on 7 May 2013. Retrieved 14 May 2013.
  8. Silberschatz, Abraham; Galvin, Peter B. (1994). ऑपरेटिंग सिस्टम अवधारणाओं (Fourth ed.). Addison-Wesley. p. 198. ISBN 0-201-59292-4.
  9. Ted Unangst (2013-06-01). "src/lib/libpthread/thread.c - संस्करण 1.71". Archived from the original on 2021-02-27. Retrieved 2022-01-25.
  10. Ted Unangst (2016-05-06). "वेबकिट में लॉकिंग पर tedu टिप्पणी - Lobsters".


बाहरी संबंध