2010-05-28 21 views
5

मैं वर्तमान में एक कोडबेस में काम कर रहा हूं जहां आईपीवी 4 पते को u_int8 पर पॉइंटर्स के रूप में दर्शाया गया है। समानता ऑपरेटर इस तरह कार्यान्वित किया जाता है:चार सरणी की तेज़ तुलना?

bool Ipv4Address::operator==(const u_int8 * inAddress) const 
{ 
    return (*(u_int32*) this->myBytes == *(u_int32*) inAddress); 
} 

यह शायद उपवास समाधान है, लेकिन यह जीसीसी संकलक चेतावनी का कारण बनता है:

ipv4address.cpp:65: warning: dereferencing type-punned pointer will break strict-aliasing rules 

मैं कैसे तुलना सही ढंग से पुनर्लेखन कर सकते हैं सख्त अलियासिंग नियमों को तोड़ने के बिना और प्रदर्शन अंक खोने के बिना?

मैं या तो memcmp या इस मैक्रो का उपयोग पर विचार किया है:

#define IS_EQUAL(a, b) \ 
    (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]) 

मैं सोच रहा हूँ कि मैक्रो सबसे तेजी से समाधान है।

आप क्या सलाह देते हैं?

अद्यतन
मैं सिर्फ लेख Squeezing performance out of memcmp usage जो बताते हैं कि कैसे संकलक (विजुअल स्टूडियो, लेकिन शायद यह भी जीसीसी) !memcmp(..) कॉल अनुकूलन कर सकते हैं पढ़ें।

+1

क्या आपने विभिन्न विकल्पों को आजमाया है और यह देखने के लिए बेंचमार्क किया है कि वास्तव में सबसे तेज़ कौन सा है? –

+0

@ निक मेयर, अभी तक नहीं, लेकिन यह एक अच्छा सुझाव है। – StackedCrooked

उत्तर

10

मैं memcmp के लिए जाना होगा()

  1. यह अधिक पोर्टेबल है
  2. मैं आमतौर पर मेरी संकलक/भाषा से होशियार नहीं बनने की कोशिश। आप स्मृति सामग्री की तुलना करने की कोशिश कर रहे हैं और (कंपाइलर विकल्पों के आधार पर भी) memcmp() के कार्यान्वयन को करने का सबसे प्रभावी तरीका होना चाहिए।

भी लगता है कि यदि आपके संकलक memcmp() इनलाइन नहीं है कि आप समारोह संदर्भ स्विच

क्या आप वाकई कि हार्ड अनुकूलित करना चाहते हैं भुगतना होगा? क्या आपने पहले से ही जांच की है कि आपका प्रोग्राम उस समय के संचालन के दौरान अपना अधिकांश समय बिताता है?

+2

हाँ, 'std :: memcmp()' std lib के अंतर्निहित सरणी की तुलना करने के लिए क्या है। मुझसे +1 यदि प्रोफाइलिंग दिखाती है कि यह एक निश्चित आर्किटेक्चर पर बहुत धीमी है, तो आप हमेशा वापस जा सकते हैं और इसे बदल सकते हैं। मुझे शक है, यद्यपि। – sbi

+1

एक अच्छी प्रोग्रामर होने का मतलब मानक टूलकिट में दिए गए टूल का उपयोग करना है। इसके अलावा, समयपूर्व अनुकूलन सभी बुराई की जड़ है। मैं पाठ्यपुस्तक प्रतिक्रियाओं की तरह उन आवाजों को जानता हूं, लेकिन वे दोनों कभी भी सबसे अच्छे और अंतर्निहित हैं, यहां तक ​​कि कभी-कभी हममें से सर्वश्रेष्ठ भी, कि वे दोहराने लायक हैं ... फिर ... और फिर ... – corsiKa

+1

आईपी पते की तुलना ' uint8' 'uint8' द्वारा पोर्टेबल भी है। तुलनात्मक रूप से छोटी मात्रा लाइब्रेरी फ़ंक्शन कॉल से अधिक कुशल होती है; हालांकि केवल प्रोफाइलिंग या असेंबली भाषा सूची सबूत दिखाएगी। –

3

जीसीसी से आपको त्रुटि मिलने का कारण यह है कि लंबाई में 1 से अधिक बाइट से अधिक कुछ भी उस ऑब्जेक्ट के साथ गठबंधन किया जाता है जो ऑब्जेक्ट आकार का एक बहु है। एक 32-बिट पूर्णांक 32-बिट सीमाओं पर शुरू करना पसंद करता है। एक char परिवर्तनीय (हस्ताक्षरित, हस्ताक्षरित या सादा), किसी भी बाइट सीमा पर हो सकता है, जैसे कि 3 जो प्रोसेसर द्वारा 32-बिट fetches के लिए अच्छा नहीं खेलता है।

आपके मामले में, 4 बाइट्स (32-बिट्स) के लिए, बाइट्स की तुलना करने के लिए कोड की तुलना में memcmp पर कॉल करने में अधिक ओवरहेड हो सकता है। this-> का उपयोग किए बिना

bool Ipv4Address::operator==(const u_int8 * inAddress) const 
{ 
    return myBytes[0] == inAddress[0] 
     && myBytes[1] == inAddress[1] 
     && myBytes[2] == inAddress[2] 
     && myBytes[3] == inAddress[3]; 
} 

देखो माँ, सदस्य समारोह कोड:

इस कोशिश करो!

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

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

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