2012-05-11 24 views
10

में एक्सर ऑपरेशन का उपयोग नहीं करते हैं मैंने पाया है कि एक्सर ऑपरेशन प्रभावी स्वैप फ़ंक्शन को लागू करने के लिए उपयोग किया जा सकता है। इस तरह:क्यों स्वैप सी ++

template<class T> 
void swap(T& a, T& b) 
{ 
    a = a^b; 
    b = a^b; 
    a = a^b; 
} 

लेकिन स्वैप के कार्यान्वयन सब मैं इंटरनेट पर पाया जा सकता है इस तरह अनिवार्य है:

template<class T> 
void swap(T& a, T& b) 
{ 
    T temp(a); 
    a = b; 
    b = temp; 
} 

ऐसा लगता है कि संकलक दो फार्म के लिए एक ही कोड जनरेट नहीं किया था उपर्युक्त क्योंकि मैंने इसे वीसी ++ 2010 पर परीक्षण किया और पहला व्यक्ति नौकरी अधिक तेज़ी से कर चुका है (और std :: swap से अधिक तेज़ है)। क्या पहले पोर्टेबल या कोई अन्य समस्या है? मेरी किसी भी गलती को सही करने के लिए स्वतंत्र महसूस करें क्योंकि मैं एक अंग्रेजी मूल नहीं हूं और सी ++ में अच्छा नहीं हूं।

+0

बस एक धारणा है: स्वैप के अपने संस्करण के साथ इस प्रयास करें कम से कम 86 सीपीयू [XCHG] (राशि http://pdos.csail.mit.edu/6.828/2008/readings/i386/XCHG.htm) निर्देश, जो तीन एक्सओआर से तेज है। – Joulukuusi

+0

क्या आपने अपना परीक्षण ऑप्टिमाइज़ेशन सक्षम के साथ चलाया? –

+2

@Joulukuusi x86 पर XCHG निर्देश कभी स्वैप प्रतिस्थापन के लिए नहीं था। मेमोरी ऑपरेंड पर इस्तेमाल होने पर इसका एक अंतर्निहित लॉक उपसर्ग होता है, इसे सिंक्रनाइज़ेशन के लिए एक उपकरण के रूप में उपयोग किया जाता है। 'XCHG reg, reg' का उपयोग संभवतः किया जा सकता है, हालांकि मुझे संदेह है कि इसकी कभी आवश्यकता है - रजिस्टरों का नाम बदलना भी तेज़ है। मैंने असेंबली की कुछ के लाइनें लिखी हैं, मैंने मूल्यों को स्वैप करने के लिए 'xchg' का उपयोग करने का आग्रह कभी नहीं किया है। – hirschhornsalz

उत्तर

18

मैंने सीखा है कि Xor आपरेशन प्रभावी स्वैप समारोह को लागू करने के

तुम गलत सीखा इस्तेमाल किया जा सकता, मुझे डर लग रहा। एक्सओआर स्वैप पुराना है: यदि यह अस्थायी मूल्य का उपयोग करने से पहले कभी भी तेजी से तेज़ था तो यह आधुनिक कंपाइलर्स और प्रोसेसर पर नहीं होना चाहिए (जहां "आधुनिक" मेरा मतलब है कि पिछले 20 वर्षों या उससे अधिक का मतलब है)। आप कहते हैं कि यह आपके लिए तेज़ था, संभवतः आपको अपना बेंचमार्क कोड दिखाना चाहिए और देखें कि दूसरों को एक ही परिणाम मिलते हैं या नहीं।

इस तथ्य के अलावा कि आपका कोड केवल पूर्णांक प्रकारों पर ही काम करता है, इसकी मूलभूत बग है।

int a = 1; 
swap(a,a); 
std::cout << a << '\n'; 
2

बेशक, क्योंकि xor चाल पीओडी प्रकारों के लिए काम करती है।

यदि आप दो उपयोगकर्ता परिभाषित, जटिल प्रकारों को स्वैप करना चाहते हैं, xor काम नहीं करेगा। आपको एक गहरी प्रतिलिपि की आवश्यकता होगी, कच्ची मेमोरी की सीधी प्रति नहीं, जो xor करता है।

संपादित करें:

मैं इसे कुलपति ++ 2010 को परीक्षण किया है और पहले एक और अधिक तेजी से काम किया जाता है (और std :: स्वैप तुलना में अधिक तेजी है)।

वास्तव में? क्या आपने डीबग मोड में संकलित किया था? आपके परिणाम क्या हैं?

4

मुझे लगता है कि सबसे स्पष्ट कारण यह है कि एक्सओआर ऑपरेटर केवल अभिन्न प्रकारों के लिए समझ में आता है।

+0

आप हमेशा ओवरलोड/हालांकि उपयुक्त प्रकार के लिए विशेषज्ञता। – Flexo

+0

हालांकि, आप बुराई कर सकते हैं। –

+0

@phresnel मानक में नहीं, मुझे उम्मीद है :) –

0

सबसे पहले, एक्सओआर ऑपरेटर केवल अभिन्न प्रकारों के लिए परिभाषित किया गया है।

दूसरा, आप गैर-अभिन्न प्रकार को अभिन्न रूप में लाने के लिए कास्टिंग चाल का उपयोग कर सकते हैं।

लेकिन तीसरे, सभी लेकिन पॉड प्रकार इस अपरिभाषित व्यवहार में परिणाम है,

और चौथा प्रकार है कि XOR आपरेशन के लिए एक अच्छी तरह से समर्थित आकार/संरेखण की जरूरत नहीं है के लिए के लिए, और अधिक twiddling की आवश्यकता होगी (लूप किया जा रहा है कम से कम बुराई)।

आप operator^ ओवरलोड सकता है, लेकिन इसका मतलब यह होता है कि swap() से प्रत्येक विशेषज्ञता यह सुनिश्चित करना चाहिए कि यह मौजूद है, या एक परिभाषित करते हैं, और यह है कि क्या इसके लायक होगा की तुलना में नाम-देखने पर अधिक भ्रम की स्थिति उपज हो सकती है। और निश्चित रूप से, यदि ऐसा ऑपरेटर पहले से मौजूद है, तो उसके पास सही व्यवहार नहीं है, और आप खराब प्रदर्शन के साथ समाप्त हो सकते हैं क्योंकि इस अधिभार को inline या constexpr आवश्यक नहीं है।

9

और प्रभावशीलता इस बात पर निर्भर करती है कि आप इसका उपयोग कहां करते हैं।

एक सामान्य CPU पर, दो पूर्णांक चर के लिए सामान्य स्वैप लग रहा है

$1 <- a 
$2 <- b 
a <- $2 
b <- $1 

4 ऑप्स, 2 भार, 2 स्टोर, और सबसे लंबे समय तक निर्भरता है 2

XOR तरह की तरह:

$1 <- a 
$2 <- b 
$3 <- $1^$2 
$4 <- $3^$2 
$5 <- $3^$4 
a <- $5 
b <- $4 

7 ऑप्स, 2 भार, 2 स्टोर, 3 लॉजिक्स, और सबसे लंबे समय तक निर्भरता 4

तो है लागू होने पर भी कम से कम सामान्य रूप से xor के साथ स्वैप धीमा है।

+1

एक आधुनिक एसएसए कंपाइलर के साथ पहला भी आसान है: 'नाम बदलें (ए 1, बी 2), नाम बदलें (बी 1, ए 2) '- एक एकल सीपीयू निर्देश नहीं, बल्कि संकलक के लिए बस एक बहीखाता चीज है। किस चर में पंजीकरण किया गया? – MSalters

संबंधित मुद्दे