2012-10-07 10 views
24

प्रश्न:धक्का बनाम mov (स्मृति के पास ढेर बनाम) की लागत, और समारोह के भूमि के ऊपर कॉल

ढेर स्मृति तक पहुँचने के रूप में एक ही गति ऐक्सेस करना है?

उदाहरण के लिए, मैं स्टैक के भीतर कुछ काम करना चुन सकता हूं, या मैं स्मृति में लेबल वाले स्थान के साथ सीधे काम कर सकता हूं।

तो, विशेष रूप से: push axmov [bx], ax के समान गति है? इसी प्रकार pop axmov ax, [bx] जैसी ही गति है? (मान bx near स्मृति में एक स्थान रखती है।) प्रश्न के लिए

प्रेरणा:

यह सी में तुच्छ कार्यों कि पैरामीटर पर ध्यान हतोत्साहित करने के लिए आम बात है।

मैंने हमेशा सोचा है कि न केवल पैरामीटर को स्टैक पर धक्का दिया जाना चाहिए और फिर फंक्शन लौटने के बाद स्टैक को पॉप अप करना चाहिए, लेकिन यह भी कि फ़ंक्शन कॉल को स्वयं को CPU के संदर्भ को संरक्षित करना होगा, जिसका अर्थ है अधिक ढेर उपयोग।

लेकिन मानते हैं कि शीर्षक वाले प्रश्न का उत्तर पता है, तो यह ओवरहेड को मापना संभव है कि फ़ंक्शन स्वयं को सेट करने के लिए उपयोग करता है (पुश/पॉप/संदर्भ को संरक्षित करता है) इत्यादि के बराबर संख्या के संदर्भ में स्मृति का उपयोग करता है। इसलिए शीर्षकबद्ध सवाल।


( संपादित: स्पष्टीकरण: near ऊपर उपयोग के रूप में की segmented memory model 16-बिट x86 आर्किटेक्चर में far करने का विरोध किया है।)

+5

वाह। मैं एक एक्सप्लोरर हूँ। मुझे बस स्टैक ओवरफ्लो पर एक अच्छा, गैर-एन 00 बी प्रश्न मिला। शैम्पेन और एक उत्थान के साथ मेरी खोज का जश्न मनाते हुए! –

+1

मैं हमेशा mov की तुलना में ईएसपी पर पुश/पॉप कॉल की कमी/वृद्धि के संचालन को ओवरहेड के रूप में मानता हूं .... लेकिन मुझे लगता है कि इसमें बहुत कुछ होना चाहिए। – loxxy

उत्तर

17

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

फ़ंक्शन कॉल आधुनिक सीपीयू पर अपेक्षाकृत सस्ते (लेकिन जरूरी नहीं कि शून्य लागत) हो सकता है, यदि वे दोहराए जाते हैं और यदि कोई अलग निर्देश कैश और विभिन्न पूर्वानुमान तंत्र है, तो कुशल कोड निष्पादन में सहायता करते हैं।

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

तो हार्डवेयर सुंदर गूंगा है (कोई या छोटे कैश, कोई भविष्यवाणी, कोई अनुदेश पुनर्व्यवस्था, कोई सट्टा निष्पादन, कुछ भी नहीं), स्पष्ट रूप से आप स्मृति दबाव और समारोह की संख्या को कम करना चाहते हैं कॉल क्योंकि प्रत्येक और हर किसी की गणना होती है ।

फिर भी एक और कारक निर्देश की लंबाई और डिकोडिंग है। ऑन-स्टैक स्थान (स्टैक पॉइंटर से संबंधित) तक पहुंचने के निर्देश किसी दिए गए पते पर मनमाने ढंग से स्मृति स्थान तक पहुंचने के निर्देशों से कम हो सकते हैं। छोटे निर्देशों को डीकोड किया जा सकता है और तेजी से निष्पादित किया जा सकता है।

मैं वहाँ सभी मामलों के लिए कोई निश्चित जवाब है, क्योंकि प्रदर्शन पर निर्भर करता है कहेंगे:

  • अपने हार्डवेयर
  • अपने संकलक
  • अपने कार्यक्रम और उसके स्मृति का उपयोग पैटर्न
+0

धन्यवाद Alexey - स्थानीय var (ढेर, सही?) बनाम वैश्विक var (स्मृति, सही?) के बारे में अच्छा बिंदु - इस तरह से इस बारे में सोचा नहीं था। –

+0

पुन: मनमाने ढंग से स्मृति स्थान - यही कारण है कि मैं विचार को 'नज़दीकी' स्मृति पर सीमित कर रहा हूं। क्या इससे कोई फर्क पड़ता है? –

+0

पुन: अलग-अलग निर्देश लंबाई और डिकोडिंग समय के बारे में आपका बिंदु - क्या आपका मतलब 'mov [bx], ax' बनाम' mov [loc], ax' के बीच एक अंतर है, 'लोक equ 0xfffd' (या कुछ ऑफ़सेट के पास)? (धन्यवाद, हमेशा के रूप में, आपके वास्तव में महान उत्तरों के लिए !!) –

11

घड़ी-चक्र-उत्सुकता के लिए ...

उन लोगों के लिए जो विशिष्ट घड़ी चक्र देखना चाहते हैं, instruction/latency tables विभिन्न प्रकार के आधुनिक x86 और x86-64 CPUs उपलब्ध हैं here (इन्हें इंगित करने के लिए हिर्शोर्नसल्ज़ के लिए धन्यवाद)।

फिर आप मिलता है, एक पेंटियम 4 चिप पर:

  • push ax और mov [bx], ax (लाल बॉक्स्ड) समान सुप्तावस्था और throughputs के साथ उनकी दक्षता में लगभग समान हैं।
  • pop ax और mov ax, [bx] (नीला बॉक्स्ड) दो बार pop ax

Pentium 4 Instruction Timing Table

जहाँ तक टिप्पणी में फॉलो-ऑन प्रश्न के रूप में की विलंबता होने mov ax, [bx] के बावजूद इसी तरह कुशल हैं, समान throughputs के साथ (3 टिप्पणी):

  • अप्रत्यक्ष पता (यानी mov [bx], ax) प्रत्यक्ष पते से भौतिक रूप से अलग नहीं है (यानी mov [loc], ax), जहां लोक एक वैरिएबल है जो तत्काल मूल्य रखता है, उदा। loc equ 0xfffd

निष्कर्ष:Alexey's thorough answer के साथ इस कम्बाइन, और वहाँ ढेर का उपयोग करने और दे संकलक तय जब एक समारोह inlined जाना चाहिए की दक्षता के लिए एक बहुत ही ठोस मामला है।

(साइड नोट: वास्तव में, यहां तक ​​कि रूप में वापस दूर 8086 के रूप में 1978 से, ढेर का उपयोग कर अभी भी नहीं कम कुशल इसी mov के रूप में these old 8086 instruction timing tables से देखा जा सकता स्मृति की तुलना में था।)


समझना विलंबता & प्रवाह

एक थोड़ा और अधिक आधुनिक CPUs के लिए समय तालिकाओं को समझने के लिए जरूरी हो सकता है।इन की मदद करनी चाहिए:

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