2010-10-21 21 views
7

मेरे पास पॉइंटर डीरफ्रेंसिंग की गति के बारे में एक प्रश्न है। मेरे पास एक संरचना है:सी संरचना सूचक डेरफ़्रेंसिंग गति

typedef struct _TD_RECT TD_RECT; 
struct _TD_RECT { 
    double left; 
    double top; 
    double right; 
    double bottom; 
}; 

मेरा सवाल यह है कि इनमें से कौन सा तेज़ होगा और क्यों?


मामला 1:

TD_RECT *pRect; 
... 
for(i = 0; i < m; i++) 
{ 
    if(p[i].x < pRect->left) ... 
    if(p[i].x > pRect->right) ... 
    if(p[i].y < pRect->top) ... 
    if(p[i].y > pRect->bottom) ... 
} 

केस 2:

TD_RECT *pRect; 
double left = pRect->left; 
double top = pRect->top; 
double right = pRect->right; 
double bottom = pRect->bottom; 
... 
for(i = 0; i < m; i++) 
{ 
    if(p[i].x < left) ... 
    if(p[i].x > right) ... 
    if(p[i].y < top) ... 
    if(p[i].y > bottom) ... 
} 

तो मामला 1 में, पाश सीधे pRect सूचक तुलना प्राप्त करने के लिए अपसंदर्भन है मान। 2 मामले में, फ़ंक्शन की स्थानीय स्थान (स्टैक पर) पर नए मान बनाए गए थे और मानों को पीआरईटी से स्थानीय चरों में कॉपी किया गया था। एक लूप के माध्यम से कई तुलना होगी।

मेरे मन में, वे समान रूप से धीमी गति से हो सकता है, क्योंकि स्थानीय चर भी ढेर पर एक स्मृति संदर्भ है, लेकिन मुझे यकीन है कि नहीं कर रहा हूँ ...

इसके अलावा, यह बेहतर होगा पी संदर्भित रखने के लिए [] इंडेक्स द्वारा, या एक तत्व द्वारा वृद्धि पी और इसे सीधे एक सूचकांक के बिना dereference।

कोई विचार? धन्यवाद :)

+13

समयपूर्व अनुकूलन के साथ अपना समय बर्बाद कर दें जो अधिकतर एक अंतर का एक स्मिडजेन नहीं बनायेगा। –

+1

शायद एक स्मीज मामलों का अंश, लेकिन अगर ऐसा होता है, तो इसका आकलन क्यों नहीं करें? – kenny

+0

Win32 के लिए, क्या मैं गति को मापने के लिए लूप को कॉल करने से पहले और बाद में मापने के लिए GetTickCount() का उपयोग कर सकता हूं, या क्या कोई बेहतर तरीका है? – oldSkool

उत्तर

1

मुझे लगता है कि दूसरा मामला तेजी से होने की संभावना है क्योंकि आप प्रत्येक लूप पुनरावृत्ति पर pRect को पॉइंटर को संदर्भित नहीं कर रहे हैं।

व्यावहारिक रूप से, अनुकूलक करने वाला एक कंपाइलर यह देख सकता है और उत्पन्न होने वाले कोड में कोई अंतर नहीं हो सकता है, लेकिन पीआरएटी में किसी आइटम का उपनाम होने की संभावना पी [] को रोक सकती है।

12

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

लेकिन यह न तो सी और न ही सी ++ प्रश्न है क्योंकि आईएसओ मानक यह नहीं करता है कि यह कैसे किया जाता है। निश्चित रूप से जांचने का सबसे अच्छा तरीका है gcc -S जैसे कुछ के साथ असेंबलर कोड उत्पन्न करना और दो मामलों की विस्तार से जांच करना।

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

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

+0

मैं पूछ रहा हूँ सुनना चाहते हैं शिखर के ... किसी भी गति की गति से मैं निचोड़ कर सकता हूं इससे मदद मिलेगी क्योंकि मुझे प्रत्येक सेक्शन को 1 डिग्री क्षेत्रों में क्लिप करने की आवश्यकता है। – oldSkool

+2

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

+0

कि आपके पास लाखों हैं, नीचे मेरी टिप्पणी देखें। अपने वेक्टर मैप पर एक इंडेक्स बनाएं (वह पी है?), एक्स और वाई द्वारा क्रमबद्ध। (क्या यह काफी स्थिर है?)। या इसे एक्स पर सॉर्ट करें और वाई पर एक इंडेक्स रखें। सभी एक्स <बाएं, सभी एक्स> दाएं, सभी वाई <शीर्ष, सभी वाई> नीचे खोजने के लिए बाइनरी खोज का उपयोग करें। तो यदि आपने 4 मिलियन कहा है कि प्रत्येक के लिए 22 तुलना है, 88 कुल, 16 मिलियन की बजाय अब आपके पास है! – CashCow

0

एक अनुकूलन कंपाइलर देखेंगे कि संरचना का उपयोग लूप इनवेरिएंट है और इसलिए Loop-invariant code motion करें, जिससे आपके दो मामले समान दिखते हैं।

3

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

के साथ युगल के भंडारण के संबंध में, आप स्थिरांक का उपयोग करके मारा कुछ प्रदर्शन मिल सकता है। आपकी सरणी कितनी बड़ी है?

साथ सूचक अंकगणित का उपयोग कर के संबंध में, यह तेजी से हो सकता है हाँ।

आप तुरन्त यदि आप जानते हैं छोड़ दिया < सही अपने रेक्ट में (यह निश्चित रूप से होना चाहिए) अनुकूलन कर सकते हैं। यदि x < छोड़ दिया गया है तो यह भी नहीं हो सकता> ठीक है ताकि आप "अन्य" में डाल सकें।

आपका बड़ा अनुकूलन, अगर वहाँ एक है, अपने सरणी में सभी आइटम लूप करने के लिए नहीं होने से आएगा और उन सभी पर 4 जांच करने के लिए नहीं है।

उदाहरण के लिए, यदि आपने एक्स और वाई पर अपनी सरणी को अनुक्रमित या सॉर्ट किया है, तो आप बाइनरी खोज का उपयोग करके, उन सभी मानों को ढूंढने में सक्षम होंगे, जिनके पास x < केवल उन लोगों के माध्यम से बाएं और लूप हैं। (- O0) प्रस्तुत दो मामलों के लिए differentcode का उत्पादन करेगा

0

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

लेकिन जैसा कि अन्य ने कहा है, कोड को असेंबलर में संकलित करें और स्वयं को देखें।

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