क्या यह XOR मूल्य स्वैप एल्गोरिदम अभी भी उपयोग या उपयोगी है


25

जब मैंने पहली बार एक मेनफ्रेम असेंबलर प्रोग्रामर का काम शुरू किया, तो उन्होंने मुझे दिखाया कि वे पारंपरिक एल्गोरिथ्म का उपयोग किए बिना मूल्यों को कैसे स्वैप करते हैं:

a = 0xBABE
b = 0xFADE

temp = a
a = b
b = temp

वे दो मूल्यों को स्वैप करने के लिए क्या करते थे - एक बिट से एक बड़े बफर तक -

a = 0xBABE
b = 0xFADE

a = a XOR b
b = b XOR a
a = a XOR b

अभी व

b == 0xBABE
a == 0xFADE

जो एक तीसरे अस्थायी स्थान की आवश्यकता के बिना 2 वस्तुओं की सामग्री की अदला-बदली करता है।

मेरा प्रश्न है: क्या यह XOR स्वैप एल्गोरिथ्म अभी भी उपयोग में है और यह अभी भी लागू है।


50
यह अभी भी दिखावा और खराब साक्षात्कार के सवालों के व्यापक उपयोग में है; यह इसके बारे में।
माइकल बोर्गवर्ड

4
क्या यह ट्रिक जैसा कुछ है: a = a + b, b = ab, a = ab?
Pieter B

4
@PieterB हाँ, वे दोनों इस stackoverflow.com/questions/1826159/…
jk के मामले हैं।

तो ... आप एक रजिस्टर बचाते हैं लेकिन 3 और निर्देशों के साथ भुगतान करते हैं। मुझे लगता है कि अस्थायी संस्करण वैसे भी तेज होगा।
बिली ओनली

1
@MSalters मान स्वैप x86g निर्देश के कारण शुरू से ही x86 में कोई समस्या नहीं है। OTOH स्वैपिंग 2 मेमोरी लोकेशन के लिए 3 xchgs की आवश्यकता होती है :)
Netch

जवाबों:


41

जब xorswapएक ही चर की आपूर्ति करने का खतरा होता है, तो फ़ंक्शन के लिए दोनों तर्कों के रूप में, जो उक्त चर को शून्य कर देता है, क्योंकि यह xorस्वयं के साथ घ है जो सभी बिट्स को शून्य में बदल देता है। बेशक इसका उपयोग एल्गोरिदम की परवाह किए बिना अवांछित व्यवहार के परिणामस्वरूप होगा, लेकिन पहली नज़र में यह व्यवहार आश्चर्यजनक और स्पष्ट नहीं हो सकता है।

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


18
यदि दोनों मान समान हैं, तो आप फिर भी सही परिणाम प्राप्त करेंगे। a: 0101 ^ 0101 = 0000; b: 0101 ^ 0000 = 0101; a: 0101 ^ 0000 = 0101;
बोबसन

1
@ GlenH7 ने क्या कहा। -1-> +1
बोबसन

1
आपको अभी भी लगता है कि "जब xorswap का उपयोग किया जा रहा है तो फ़ंक्शन के लिए दोनों तर्कों के समान वेरिएबल की आपूर्ति करने का खतरा है जो उक्त चर को शून्य करता है क्योंकि यह अपने साथ xor'd होता है जो सभी बिट्स को शून्य में बदल देता है।" .. क्या इसका मतलब नहीं निकाला गया था?
क्रिस

9
@ क्रिस नहीं, पहले मैंने लिखा था कि यदि मान समान थे a=10, b=10, और यदि आपने ऐसा किया xorswap(a,b)तो काम करेंगे और उन चर को शून्य नहीं करेंगे जो झूठे हैं और अब हटा दिए गए हैं। लेकिन अगर आप ऐसा करते xorswap(a, a)तो aशून्य हो जाता, जिसका मैं मूल रूप से मतलब था लेकिन मूर्खतापूर्ण था। :)
zxcdw 18

3
यह कुछ भाषाओं में बहुत प्रासंगिक है - छोटे छोटे खतरे जैसे कि भविष्य में बग का पता लगाना मुश्किल हो जाता है जब दो बिंदुओं से निपटना होता है जो किसी तरह एक ही पते पर 100+ लाइनों को इंगित करने के लिए सेट होते हैं जो आपको दिखाई नहीं देते हैं।
ड्रेक क्लेरिंस

14

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

इन बीते दिनों में, रजिस्टर और मेमोरी दोनों दुर्लभ थे और किसी भी बाइट या मेमोरी के लिए भीख मांगने के लिए कोई ट्रिक नहीं थी, लीड आर्किटेक्ट से मेमोरी का समय बच गया था - दोनों कोड और निष्पादन समय लिखने में।

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

यह फिर से उपयोगी हो सकता है अगर कोई विशेष रूप से सीमित माइक्रोकंट्रोलर में काम कर रहा है, लेकिन एक स्वैप का अनुकूलन करने से किसी की समस्या का स्रोत होने की संभावना नहीं है - बहुत चालाक होने की कोशिश करना एक समस्या है।


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

8

क्या ये काम करेगा? हाँ।

क्या आपको इसका इस्तेमाल करना चाहिए? नहीं।

माइक्रो-ऑप्टिमाइज़ेशन के इस प्रकार से समझ में आएगा:

  • आपने कोड को देखा है कि कंपाइलर ऐसा करने के सीधे तरीके (असाइनमेंट और एक अस्थायी) के लिए उत्पन्न होता है और यह निर्णय लिया कि XOR का दृष्टिकोण अधिक तेज़ कोड बनाता है

  • आपने अपने ऐप को प्रोफाइल कर लिया है, और सीधे दृष्टिकोण की लागत को कोड की स्पष्टता से बाहर कर दिया है (और परिणामस्वरूप स्थिरता में बचत)

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

दूसरे बिंदु पर, आप जोड़ा जटिलता के लिए क्या हासिल कर रहे हैं? यहां तक ​​कि अगर आपने मापा और XOR दृष्टिकोण को तेजी से पाया है, तो क्या यह कम स्पष्ट दृष्टिकोण को सही ठहराने के लिए पर्याप्त प्रभाव है? आपको कैसे मालूम?

अंत में, आपको यह देखना चाहिए कि क्या आपके प्लेटफ़ॉर्म / भाषा के लिए कोई मानक स्वैप फ़ंक्शन है - C ++ STL, उदाहरण के लिए, एक टेम्पलेट स्वैप फ़ंक्शन प्रदान करता है जो आपके कंपाइलर / प्लेटफ़ॉर्म के लिए अत्यधिक अनुकूलित होगा।


2

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

लेकिन कोई इसका उपयोग करने से ध्यान रखेगा कि ये दोनों स्थान समान नहीं हो सकते क्योंकि बाद वाले मामले में यह प्रभावी रूप से दोनों मूल्यों को शून्य कर देगा। इसलिए आमतौर पर यह स्पष्ट मामलों तक सीमित होता है जैसे रजिस्टर और मेमोरी लोकेशन का आदान-प्रदान।

X86 के साथ, xchg और cmpxchg निर्देश अधिकांश मामलों में आवश्यकता को पूरा करते हैं, लेकिन RISCs आम तौर पर उनके साथ (स्पार्क को छोड़कर) कवर नहीं किया जाता है।

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