2010-03-12 9 views
6

मुझे लगता है कि जैसे कुछ सी कोड पढ़ रहा हूँ:सी में संरचना, वे कुशल हैं?

double function(int lena,double xa,double ya, double za, double *acoefs, ..., 
       int lenb,double xb,double yb, double zb, double *bcoefs, ..., 
       same for c, 
       same for d) 

इस समारोह 100,000 बार से कोड मोर में कहा जाता है तो यह प्रदर्शन के लिए महत्वपूर्ण है।

मैं इस कोड का विस्तार करने की कोशिश कर रहा हूँ, लेकिन मैं जानना चाहता हूँ अगर यह कुशल है या नहीं (और कितना इस गति को प्रभावित करती है) इस

struct PGTO { int len; double x,y,z ; double *acoefs } 

और उसके बाद की तरह एक struct में सभी मापदंडों को संपुटित करने के लिए समारोह में पैरामीटर का उपयोग करें।

+11

पता लगाने का आसान तरीका: प्रोफ़ाइल और परीक्षण – cobbal

+1

संकलित कोड x86 और एआरएम मानक कॉल सम्मेलन के लिए समान होना चाहिए। – kennytm

+0

क्या '...' varargs को इंगित करता है या आपने कुछ पैरामीटर छोड़े हैं? – bk1e

उत्तर

5

विज़ुअल सी ++ 2008 64 बिट कॉलर को ढेर पर संरचना की एक प्रति के लिए स्थान आवंटित करके और डेटा आइटम को कॉपी करने के द्वारा संरचना को पास करने लगता है और उसके बाद उस प्रतिलिपि के पते को फ़ंक्शन में पास करके पास कर रहा है ।

यह सरल उदाहरण के रूप में संकलित इस प्रकार है - तो मूल रूप से जब आप अलग-अलग आइटम फोन करने वाले उन्हें ढेर पर धकेल दिया पारित

movsx eax, BYTE PTR [rcx+12] 
add eax, DWORD PTR [rcx+8] 
add eax, DWORD PTR [rcx+4] 
add eax, DWORD PTR [rcx] 
movd xmm0, eax 
cvtdq2ps xmm0, xmm0 
addss xmm0, DWORD PTR [rcx+16] 
unpcklps xmm0, xmm0 
cvtps2pd xmm0, xmm0 
ret 0 

और समारोह के लिए उन्हें के सापेक्ष तक पहुँचता है -

struct data { 
    int a; 
    int b; 
    int c; 
    char d; 
    float f; 
}; 




double f2(data d) 
{ 
    return d.a+d.b+d.c+d.d+d.f; 
} 

यह करने के लिए संकलित ढेर। जब आप एक स्ट्रिक्यूचर पास करते हैं तो कॉलर डेटा आइटम को स्टैक पर मेमोरी के ब्लॉक में कॉपी करता है और उसके बाद उस पते को उस फ़ंक्शन में पास करता है, जो उसके सापेक्ष उन्हें एक्सेस करता है।

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

मेरी राय में एक struct का उपयोग कर साफ है और वहाँ कोई महत्वपूर्ण मतभेद गति में तो हमेशा की तरह है कि एक :)

के लिए जाते हैं, अगर प्रदर्शन के ऊपर संदेह में आप अपने सटीक सेटअप प्रोफ़ाइल करने की आवश्यकता प्रतीत

5

इस प्रश्न का उत्तर मंच और उसके कॉलिंग सम्मेलनों पर बहुत अधिक निर्भर करता है। यह गीलेर पर भी निर्भर करता है कि फ़ंक्शन को रेखांकित किया जा सकता है और अन्य कंपाइलर अनुकूलन भी हो सकते हैं।

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

वैसे भी, प्रश्न का आसानी से उत्तर नहीं दिया जा सकता है। तो, जैसा कि सभी प्रदर्शन विचारों के साथ: बस परीक्षण और प्रोफाइल!

+1

यदि आप संरचना में पॉइंटर पास करते हैं, तो आप संदर्भ से गुज़र रहे हैं, मूल्य से नहीं। –

0

आधुनिक कंपाइलर्स संभवतः दोनों मामलों में समान कोड उत्पन्न करेंगे। इसलिए, जब तक कि आपका कंपाइलर अत्याधुनिक नहीं है, केवल एकमात्र (लेकिन महत्वपूर्ण) लाभ आपको संरचनाओं के साथ मिलेगा पठनीयता में सुधार हुआ है।

+2

नहीं, यह नहीं कर सकता। कॉलिंग सम्मेलनों को स्टैक पर पारित होने वाले तर्कों की आवश्यकता होती है। संकलक कॉलिंग सम्मेलनों को तब तक नहीं रोक सकता जब तक कि फ़ंक्शन को 'स्थिर' घोषित न किया जाए। यह आम तौर पर मामला नहीं है। –

+0

आप सही हैं, मैं इसके बारे में भूल गया। –

+0

@ यह कैसे है कि structs और एकल पैरामीटर के बीच एक अंतर है? दोनों मामलों में, पैरामीटर को ढेर पर कॉपी किया जाएगा। –

0

सबसे अच्छी बात प्रोफाइल और परीक्षण करना है।

लेकिन, एक बात, जब आप संरचना के लिए एक सूचक पास करते हैं तो कम पैरामीटर स्टैक पर कॉपी किए जाएंगे। साथ ही, आप कॉल कॉल अधिक साफ दिख सकते हैं।

4

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

संरचना में पॉइंटर पास करना आम तौर पर कई पैरामीटर पारित करने से सस्ता है।

+3

यदि आप फ़ंक्शन को कॉल करते समय हर बार संरचना को भरने की आवश्यकता नहीं है। – lhf

+0

निश्चित रूप से, लेकिन, एक बार फिर, यह कॉलिंग कोड और शेष स्रोत पर निर्भर करता है :) विचार करने के लिए बहुत सारे कारक हैं। –

0

हां, वे हैं। अगर मैं इतना अधिक था, तो मैं एक लाख रुपये शर्त लगाऊंगा, कि प्रदर्शन अंतर नगण्य है।

0

एक संरचना या तर्क सूची पास करने से पूरी तरह से कोई फर्क नहीं पड़ता है। कॉलिंग सम्मेलन को मूल्य से पारित करने और स्टैक के माध्यम से पारित करने की आवश्यकता होती है (जब तक कि समारोह static घोषित नहीं किया जा सकता)।

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

+0

क्या "कॉलिंग कन्वेंशन" का मतलब सभी कॉलिंग सम्मेलन है? आपके द्वारा देखे गए सभी कॉलिंग सम्मेलन? 'Cdecl' कॉलिंग सम्मेलन? –

1

मुझे लगता है कि यह इस बात पर निर्भर करता है कि आपको संरचना को कितनी बार भरना है।

एक स्ट्रक्चर (4 बाइट्स) में एक पॉइंटर पास करने से इंट, 3 डबल्स और पॉइंटर (32 बाइट्स) पास करने से कम निर्देश होंगे, लेकिन अगर आपको उन 32 बाइट्स के साथ स्ट्रक्चर को भरना होगा कॉल करें, तो आप लाभ खो चुके हैं।

किसी भी दर पर, प्रदर्शन हमेशा सापेक्ष होता है, इसलिए यह बताने का एकमात्र तरीका यह है कि यह उचित है या नहीं, यह तर्क देखना है कि उन तर्कों को पारित करने में कितना प्रतिशत खर्च किया जाता है। ऐसा करने के लिए, मैं बस इसे चलाता हूं और इसे 10 या 20 बार यादृच्छिक रूप से रोकता हूं। जब तक मैं उन तर्कों को पारित करने के 10% से अधिक समय तक नहीं पकड़ता, संभावना है कि बड़ी समस्याएं हैं जिन्हें पहले तय किया जा सकता है।

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