2010-01-07 26 views
14

मेरे पास एक ऐसा फ़ंक्शन है जो डेटा के टुकड़े पर चल रहा है (मान लें, int), और मैं इसे वैल्यू के संदर्भ को पास करके इसे बदलना चाहता हूं। इस प्रकार, मेरे पास कार्य है: void myFunction(int *thing) { ... }। जब मैं इसका उपयोग करता हूं तो मैं इसे इस प्रकार कहता हूं: myFunction(&anInt)क्या जीसीसी एक ऐसा फ़ंक्शन इनलाइन करेगा जो सूचक लेता है?

जैसा कि मेरे फ़ंक्शन को अक्सर कहा जाता है (लेकिन कई अलग-अलग स्थानों से) मैं इसके प्रदर्शन के बारे में चिंतित हूं। मैंने इसे फ़ंक्शन में दोबारा सुधारने का कारण टेस्टेबिलिटी और कोड पुन: उपयोग किया है।

क्या संकलक फ़ंक्शन को अनुकूलित करने में सक्षम होगा, इसे सीधे मेरे anInt चर पर संचालित करने के लिए इनलाइन कर देगा?

मुझे उम्मीद है कि आप इस सवाल को उस भावना में लेंगे जिसमें यह पूछा गया है (यानी मैं अनुकूलन के बारे में समय से पहले चिंता नहीं कर रहा हूं, मैं जवाब के बारे में उत्सुक हूं)। इसी प्रकार, मैं इसे मैक्रो में नहीं बनाना चाहता हूं।

उत्तर

9

जीसीसी काफी स्मार्ट है। इस कोड को टुकड़ा पर विचार करें:

#include <stdio.h> 

void __inline__ inc(int *val) 
{ 
    ++ *val; 
} 

int main() 
{ 
    int val; 

    scanf("%d", &val); 

    inc(&val); 

    printf("%d\n", val); 

    return 0; 
} 

एक gcc -S -O3 test.c आप निम्नलिखित प्रासंगिक एएसएम मिल जाएगा के बाद:

... 
call __isoc99_scanf 
movl 12(%rsp), %esi 
movl $.LC1, %edi 
xorl %eax, %eax 
addl $1, %esi 
movl %esi, 12(%rsp) 
call printf 
... 

आप देख सकते हैं, इंक को देखने के लिए एक एएसएम विशेषज्ञ होने की कोई आवश्यकता नहीं है() कॉल को एक वृद्धि निर्देश में परिवर्तित कर दिया गया है।

+0

कम से कम जीसीसी 4.4.2 के साथ, इसे 'इनलाइन' चिह्नित करने की भी आवश्यकता नहीं है! (हालांकि 'स्थिर' का उपयोग जेनरेट बाइनरी में फ़ंक्शन की एक अतिरिक्त प्रति से बच जाएगा।) – ephemient

6

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

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

int x = 42; 
int * p = & x; 
* p = * p + 1; 

x = x + 1; 

में यह और अधिक कठिन के लिए अनुकूलक को देखने के लिए है।

+0

मैं मंच पर बिल्कुल नहीं हूं जहां मैं असेंबली आउटपुट पढ़ने के लिए तैयार हूं! – Joe

+0

'x' और' p' के साथ अपना सबसे हालिया संपादन पुन: हाँ, यह वही प्रश्न है जो मैं पूछ रहा हूं। मुझे पता है कि यह मुश्किल है, यही कारण है कि मैं पूछ रहा था कि यह संभव था या नहीं! – Joe

+0

जैसा कि मैंने कहा, यह संभव है। क्या जीसीसी मैं करता हूं? मुझे नहीं पता। –

-1

आप किस कंपाइलर संस्करण का उपयोग कर रहे हैं? किस विकल्प के साथ? किस मंच पर?

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

1

यह (या कम से कम कर सकता है) होगा। ऐसे कुछ कारण हैं जहां फ़ंक्शन को रेखांकित नहीं किया जा सकता है - उदा। जब आप फ़ंक्शन के पॉइंटर तक पहुंचने का प्रयास करते हैं (संदर्भ द्वारा कॉलिंग फ़ंक्शन - आप संदर्भ द्वारा पैरामीटर तक पहुंच रहे हैं जो ठीक है)। अन्य स्थिति हो सकती है (स्थैतिक चर? अनिश्चित)

"बाहरी इनलाइन" के साथ फ़ंक्शन घोषित करने का प्रयास करें - यह संकलक को स्टैंडअलोन निकाय को उत्सर्जित करने से रोकता है। यदि यह फ़ंक्शन इनलाइन नहीं कर सकता है, तो यह एक त्रुटि को छोड़ देगा।

+0

सी 99 का कहना है कि 'बाहरी इनलाइन' स्टैंड-अलोन ऑब्जेक्ट कोड उत्पन्न होने का कारण बनता है, और सीसीसी मोड में डाले जाने पर जीसीसी इन विषम नियमों का पालन करेगा। अन्यथा, जीसीसी का डिफ़ॉल्ट व्यवहार वह है जो आपने कहा है। (सी 8 9 कुछ भी नहीं कहता है, और तर्कसंगत रूप से वे बेहतर अर्थशास्त्र हैं।) – ephemient

2

इससे कोई फर्क नहीं पड़ता कि तर्क एक सूचक है या नहीं।

लेकिन पहले, अगर संकलक स्वचालित रूप से इनलाइन समारोह, यह होना चाहिए चाहिए स्थिर। और यह एक ही संकलन इकाई में निहित होना चाहिए। नोट: हम सी के बारे में बात कर रहे हैं, सी ++ नहीं। सी ++ इनलाइन नियम अलग-अलग हैं।

यदि समान संकलन इकाई में फ़ंक्शन होना संभव नहीं है, तो वैश्विक अनुकूलन आज़माएं (विवरण के लिए अपने कंपाइलर के दस्तावेज़ देखें)।

सी 99 आपको एक "इनलाइन" कीवर्ड देता है, जैसा कि सी ++ में है। जो संकलन इकाई को प्रतिबंध लेता है।

यहां कुछ further information है।

 
-Winline 
    Warn if a function can not be inlined and it was declared as inline. 
    Even with this option, the compiler will not warn about failures to inline 
    functions declared in system headers. 

    The compiler uses a variety of heuristics to determine whether or not to 
    inline a function. For example, the compiler takes into account the size 
    of the function being inlined and the amount of inlining that has already 
    been done in the current function. Therefore, seemingly insignificant 
    changes in the source program can cause the warnings produced by -Winline 
    to appear or disappear. 
+2

जैसा कि सी 8 9 इनलाइनिंग के बारे में कुछ भी नहीं कहता है, एक सी 8 9 संकलक निश्चित रूप से किसी भी कार्य को इनकार करने के लिए स्वतंत्र है। बेशक, ऐसा कोई प्रोग्राम लिंक नहीं कर सकता है (जो यहां असली मुद्दा है), लेकिन एक कंपाइलर जो एक एकीकृत लिंकर वैश्विक कोड विश्लेषण करके इसे गोल कर सकता है। –

+0

तो मुझे लगता है कि, एक कंपाइलर स्वचालित रूप से गैर स्थैतिक कार्यों को रेखांकित कर सकता है यदि सभी फ़ाइलों को एक ही चरण में निष्पादन योग्य (किसी ऑब्जेक्ट फ़ाइल या लाइब्रेरी में नहीं) में संकलित और लिंक किया गया हो। खैर, ठीक है, लेकिन यह आमतौर पर बहुत व्यावहारिक नहीं है;) "स्थिर होना चाहिए" नियम अभी भी अन्यथा लागू होता है। – Frunsi

+1

अनुकूलक सेटिंग्स, फ़ंक्शन का आकार, कॉल की आवृत्ति इत्यादि के आधार पर, जीसीसी एक ही संकलन इकाई के भीतर गैर स्थैतिक कार्यों को रेखांकित करेगा। यह अभी भी एक गैर-इनलाइन फ़ंक्शन उत्पन्न करेगा। – ephemient

18

एक तरह से करता है, तो समारोह inlined है -Winline जीसीसी विकल्प का उपयोग करने के लिए है। क्या आप वास्तव में जानते हैं कि यहां एक प्रदर्शन समस्या है? आपके मूल्यवान समय को लेकर चिंतित एक मूल्य। मेरा मतलब है, वास्तव में पता है? जैसे, क्या आपने इसे माप लिया है?

अपने आप से यह बहुत बुरा नहीं है, लेकिन यदि आप इस रवैये को बड़ी मात्रा में कोड पर लेते हैं, तो आप कुछ गंभीर नुकसान कर सकते हैं और किसी भी अच्छे कारण के लिए बड़ी मात्रा में अपवित्रता और रखरखाव का समय बर्बाद कर सकते हैं।

+0

अद्भुत खोज –

+0

हालांकि यह डिफ़ॉल्ट विनाशकों के बारे में बहुत सारी नकली चेतावनियों को थूकता है> _ < –

-1

यह समय से पहले अनुकूलन के एक क्लासिक मामले की तरह मुझे लग रहा है: पता लगाने के लिए

+0

जैसा कि मैंने सवाल में कहा था, मैं अनुकूलन के बारे में चिंता नहीं कर रहा हूं, मैं भाषा और जीसीसी के बारे में अधिक जानने की कोशिश कर रहा हूं। मैं निश्चित रूप से अनुकूलन से पहले मापने में विश्वास करता हूं लेकिन मुझे लगता है कि कम से कम इन चीजों को जानना उपयोगी है। – Joe

0

यदि आप संकलक उपरोक्त कोड उत्पन्न करने वाले संकलक के बारे में चिंतित हैं और एक साधारण वैल्यूटाइप बदलना चाहते हैं, तो अपने कार्य को int myFunction(int) के रूप में घोषित करें और नया मान वापस करें।

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

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