2009-08-25 20 views
9

के लिए प्रत्यक्ष सदस्य पहुँच बनाम कहो मैं निम्नलिखित की तरह एक struct है ...सी संकेत structs

typedef struct { 
    int WheelCount; 
    double MaxSpeed; 
} Vehicle; 

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

double LocalSpeed = MyGlobal.MaxSpeed; 

या

double LocalSpeed = pMyGlobal->MaxSpeed; 

मेरी कार्यों में से एक को सरल बनाने और एक हाल ही में विरासत में मिला एम्बेडेड सिस्टम ठीक करने के लिए है।

+1

एक पॉइंटर आपको उस सीधी पहुंच के साथ क्या प्रदान करता है? और एक सूचक धीमा है। –

+3

-1 माइक्रो-ऑप्टिमाइज़ेशन के बारे में पूछने के लिए पहले इसे बेंचमार्किंग के बिना। – bk1e

उत्तर

19

सामान्य तौर पर, मैं कहना चाहता हूँ पहले विकल्प के साथ जाना:

double LocalSpeed = MyGlobal.MaxSpeed; 

यह एक कम भिन्नता (आप सूचक नहीं मिलता, तो फिर अपसंदर्भन यह स्थान है करने के लिए इसे पाने के लिए) है। यह पढ़ने और बनाए रखने के लिए भी आसान और आसान है, क्योंकि आपको संरचना के अलावा पॉइंटर चर बनाने की आवश्यकता नहीं है।

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

+0

डाउनवॉट्स क्यों? मैं उत्सुक हूं कि लोग असहमत क्यों हैं। –

+1

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

+0

पॉइंटर डीरफ्रेंसिंग के लिए, मैंने जो सोचा था, यह अभी काफी लंबा रहा है क्योंकि मुझे सी या सी ++ से निपटना पड़ा है। आपकी सलाह के लिए धन्यवाद दोस्तों। –

1

मुझे लगता है कि, यदि इससे कोई फर्क पड़ता है, तो यह वास्तुकला-निर्भर होगा।

1

सी में, कोई अंतर नहीं होना चाहिए, या एक महत्वहीन प्रदर्शन हिट होना चाहिए।

सी छात्रों को सिखाया जाता है:

pMyGlobal->MaxSpeed == (*pMyGlobal).MaxSpeed 

आपको लगता है कि वे मूलतः एक ही हैं उन दोनों को अपने आप को समझाने के लिए के disassembly की तुलना करने में सक्षम होना चाहिए, भले ही आप एक सभा-कोड प्रोग्रामर नहीं हैं।

यदि आप प्रदर्शन अनुकूलन की तलाश में हैं, तो मैं कहीं और देखूंगा। आप इस प्रकार के माइक्रो-ऑप्टिमाइज़ेशन के साथ पर्याप्त CPU चक्रों को सहेजने में सक्षम नहीं होंगे।

स्टाइलिस्ट कारणों से, मैं स्ट्रक्चर-डॉट नोटेशन पसंद करता हूं, खासकर सिंगलटन-ग्लोबल्स से निपटने पर। मुझे इसे पढ़ने के लिए बहुत साफ लगता है।

+1

प्रश्न इस बारे में नहीं है -> बनाम *, यह पहली जगह में एक सूचक का उपयोग करने के बारे में है। –

+1

सवाल यह है: "क्या यह संरचना के सदस्यों को सीधे या सूचक के माध्यम से एक्सेस करना तेज़ है?" मेरा मानना ​​है कि मैंने इस सवाल को संबोधित किया। – abelenky

8

पहला व्यक्ति तेज़ होना चाहिए क्योंकि इसे पॉइंटर डीरफ्रेंसिंग की आवश्यकता नहीं होती है। फिर फिर यह x86 आधारित सिस्टम के लिए सच है, दूसरों के लिए निश्चित नहीं है।

86 पर पहले एक इस

mov eax, [address of MyGlobal.MaxSpeed] 

और दूसरा एक की तरह कुछ करने के लिए अनुवाद होगा इस

mov ebx, [address of pMyGlobal] 
mov eax, [ebx+sizeof(int)] 
1

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

3

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

शायद आपके सिस्टम के अधिक स्पष्ट प्रदर्शन क्षेत्र हैं।

3
struct dataStruct 
{ 
    double first; 
    double second; 
} data; 

int main() 
{ 
    dataStruct* pData = &data; 

    data.first = 9.0; 
    pData->second = 10.0; 
} 

इस विधानसभा उत्पादन का उपयोग कर VS2008 रिलीज़ मोड है:

data.first = 9.0; 
008D1000 fld   qword ptr [[email protected] (8D20F0h)] 

    pData->second = 10.0; 
008D1006 xor   eax,eax 
008D1008 fstp  qword ptr [data (8D3378h)] 
008D100E fld   qword ptr [[email protected] (8D20E8h)] 
008D1014 fstp  qword ptr [data+8 (8D3380h)] 
+1

अब अपने एम्बेडेड प्लेटफ़ॉर्म को लक्षित करें। – Alan

+0

अनुकूलन सेटिंग्स क्या थीं? –

+0

यह गलत है। आपका पहला सदस्य हमेशा एक संरचना की परिभाषा से जीत जाएगा (एक संरचना का सूचक भी पहले सदस्य का सूचक है)। आपको दूसरे बनाम दूसरे की तुलना करनी चाहिए। –

2

अलग करना, एकत्रित न, एकत्रित न ...

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

1) एकत्रित न और जांच 2) समय निष्पादन

ऊपर हालांकि लब्बोलुआब यह है यह बजाय एक से दो निर्देश का मामला एक भी घड़ी की लागत हो सकता है उल्लेख किया है चक्र जो आप कभी नहीं देख पाएंगे। आपके कंपाइलर और ऑप्टिमाइज़र विकल्पों की गुणवत्ता प्रदर्शन में सुधार की उम्मीद में कोड की एक पंक्ति को ट्विक करने की कोशिश करने से कहीं अधिक नाटकीय प्रदर्शन अंतर करने जा रही है। स्विचिंग कंपाइलर्स आपको कभी-कभी दिशा में 10-20% दे सकते हैं। जैसा कि आपके अनुकूलन झंडे को बदल सकता है, सबकुछ चालू करने से सबसे तेज़ कोड नहीं होता है, कभी-कभी -O1 -O3 से बेहतर प्रदर्शन करता है।

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

typedef struct 
{ 
    unsigned int first; 
    unsigned int second; 
} dataStruct; 

dataStruct data; 

int main() 
{ 
    dataStruct *pData = &data; 

    data.first = 9; 
    pData->second = 10; 

    return(0); 
} 
जीसीसी के साथ

आपको मिलता है::

इस प्रश्न पर किसी और के उदाहरण का उपयोग

mov r2, #10 
mov r1, #9 
stmia r3, {r1, r2} 

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

या कोई अनुकूलन के साथ, एक ही कोड, एक ही कंपाइलर, सूचक और प्रत्यक्ष के बीच कोई अंतर नहीं।

mov r3, #9 
str r3, [r2, #0] 

mov r3, #10 
str r3, [r2, #4] 

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

तो आपके प्रश्न का उत्तर पूर्ण नहीं है ...निर्भर करता है। अलग करना और परीक्षण करना।

+0

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

+0

यह गलत है। आपका पहला सदस्य हमेशा एक संरचना की परिभाषा से जीत जाएगा (एक संरचना का सूचक भी पहले सदस्य का सूचक है)। आपको दूसरे बनाम दूसरे की तुलना करनी चाहिए। –

0

डायरेक्ट सदस्य का उपयोग तेज़ है (पॉइंटर्स के लिए आपको एक पॉइंटर डेरफरेंस ऑपरेशन अधिक मिलता है)। हालांकि मुझे ऐसी स्थिति में कल्पना करने में कठिनाई हो रही है जहां यह एक समस्या, प्रदर्शन या अन्यथा होगा।

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