2009-11-24 10 views
5

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

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

+1

इस बात का कोई सबूत नहीं है कि भाषा के खिलाफ जा रहे हैं और कौन से कंपाइलर्स "अनुकूलित" हैं, जिससे आपको प्रदर्शन बढ़ावा मिलेगा। – AraK

+3

जब से एल्गोरिदम में सुधार हो रहा है, ऑप्टिमाइज़ करने से पहले प्रोफाइलिंग आदि उचित है? यदि यह सच था, तो हमें इन चीजों को करने के लिए लोगों को मनाने के लिए इतना कठिन काम नहीं करना पड़ेगा। – jason

+0

मैंने फिर से खोलने के लिए मतदान किया। मुझे एक उत्तर जोड़ने के लिए पसंद आया होगा, अर्थात् यह लिंक: http://stackoverflow.com/questions/926266/performance-optimization-strategies-of-last-resort/927773#927773 –

उत्तर

18

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

+1

+1 वाह। मैंने कभी ऐसी तकनीक के बारे में कभी नहीं सुना है। – poundifdef

+0

यह वास्तव में +6 के लायक नहीं है, क्योंकि यह सभी अपरंपरागत नहीं है और सवाल के खिलाफ चला जाता है .......लेकिन यह उचित है इसलिए मैं आपको या तो डाउनवोट नहीं कर सकता: \ – mpen

+4

@ मार्क: यह एक मजाक है, यह कहकर कि अनुकूलित करने का पूरी तार्किक तरीका "अपरंपरागत" है क्योंकि कुछ लोग वास्तव में ऐसा करते हैं। –

6

Duff's Device कैननिकल उदाहरण है। यह इतना अजीब बात है कि टॉम डफ ने स्वीकार किया, "यह कोड किसी भी प्रकार के तर्क [मामले के वक्तव्य में गिरावट के बारे में बहस] में तर्क देता है, लेकिन मुझे यकीन नहीं है कि यह इसके लिए या उसके खिलाफ है"।

4

अपना कोड प्रोफ़ाइल, धीमी गति से स्पॉट ढूंढें, और उन्हें अनुकूलित करने के लिए इनलाइन असेंबली का उपयोग करें।

+2

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

+1

आप चरण 4 भूल गए: यह सुनिश्चित करने के लिए फिर से प्रोफ़ाइल करें कि आपकी इनलाइन असेंबली वास्तव में कोड को धीमा नहीं करती है। मैंने देखा है कि ऐसा होता है। –

1
+0

और कारमाक कारमैक नहीं है। – Nosredna

+0

सही, लेकिन यह इस तरह के रूप में जाना जाता है। – jason

+1

यह आमतौर पर अधिकांश आधुनिक हार्डवेयर पर प्रदर्शन * जुर्माना * है (क्योंकि अधिकांश आर्किटेक्चर में हार्डवेयर पारस्परिक वर्ग रूट निर्देश होता है जो एफपी डोमेन में रहता है)। –

3

आप सी को अनुकूलित करने के लिए एक अपरंपरागत, कोई धारण-बाधित, अभी तक सामान्य उद्देश्य समाधान की तलाश में हैं?

इसे असेंबली भाषा में लिखें।

3

1) लूप अनोलिंग। यदि आप वास्तव में लूप नहीं करते हैं तो आप प्रत्येक पुनरावृत्ति को कूद, तुलना और वृद्धि को बचाते हैं।
2) डबल-इंडिकेशन से बचें। आमतौर पर अंकगणित करने के लिए यह तेज़ होता है कि पुनर्प्राप्ति, इसलिए एक [y * ऊंचाई + x] आमतौर पर [y] [x] से तेज़ होता है। इसके अलावा आकार का एक आयामी सरणी एमएक्सएन आयाम एमएक्सएन के आयताकार मैट्रिक्स की तुलना में एम (या एन) शब्दों के पॉइंटर्स के लायक बचाता है।
3) जब भी संभव हो हास्यास्पद असेंबली अनुकूलन का उपयोग करें। उदाहरण के लिए, x86 आर्किटेक्चर पर, आप सामान्य temp=a; a=b; b=temp; पैटर्न के बजाय एक ऑपरेशन में बाइट्स को स्वैप करने के लिए बीएसडब्ल्यूएपी निर्देश का उपयोग कर सकते हैं।

और बेशक, यह मत भूलना:
4) सीमाओं की जांच या त्रुटि प्रबंधन न करें।

ऐसा कहा जा रहा है कि, मैं अभ्यास में छोड़कर इन सभी को छोड़ दूंगा।

+1

सिवाय इसके कि इसमें से अधिकांश बेकार है क्योंकि संकलक इसे करेगा। –

+1

ज्यादातर मामलों में "अपरंपरागत अनुकूलन" व्यर्थ हैं - यह इंगित करते हुए कि एक व्यर्थ प्रश्न के उत्तर स्वयं को व्यर्थ है ... व्यर्थ है। (सी: – Dathan

+0

कंपिलर स्वचालित रूप से 1 और 2 नहीं कर सकते हैं? और इस तरह के चीजों के लिए असेंबली हैक से भरा पुस्तकालय नहीं होना चाहिए? – mpen

5

Abusing the constant 0x5f3759df व्युत्क्रम वर्ग जड़ों की गणना करने के लिए जल्दी से सुंदर उच्च रैंक प्राप्त करने है ...

1

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

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

4

इनलाइन असेंबली का उपयोग करें?

गंभीरता से हालांकि, अगर सी कोड को बदलकर आप प्रदर्शन में सुधार कर सकते हैं, संभावना है कि आप इसे साफ कर सकते हैं।

कुछ अपवादों को छोड़कर:

1) आप विभिन्न प्रकार के संकेत दिए गए अक्सर आप संकेत दिए गए कि तकनीकी रूप से एक सीमा लंघन हालत के लिए अपने आवेदन को बेनकाब पर ब्लॉक कार्रवाई कर सकते हैं के लिए संरेखण अर्थ विज्ञान पर भरोसा कर रहे हैं, लेकिन व्यवहार में तो नहीं है आपके सिस्टम की संरेखण विशेषताओं के कारण। इसलिए प्रारंभिक चार के संरेखित करके एक स्मृति प्रतिलिपि की जा सकती है, फिर आंतरिक ब्लॉक को लंबे * सूचक का उपयोग करके किया जा सकता है।

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

3) यूनियन हमेशा थोड़ी "हैकी" होती हैं हालांकि आप उनका उपयोग करते हैं। यह काफी ढीली प्रकार की जांच के साथ बहुरूपता को लागू करने का एक तरीका है।

4) सी प्रीप्रोसेसर का उपयोग ऑटो-जनरेटिंग कोड के तरीके के रूप में आमतौर पर डीबग और पढ़ने के लिए बहुत मुश्किल होता है। जैसे-जैसे लोग इससे बचते हैं।

1

डीएसपी अनुप्रयोगों में, सिमड निर्देशों से सर्वश्रेष्ठ प्रदर्शन प्राप्त करने के लिए असेंबली भाषा में जाने के लायक है कि सी कंपाइलर्स बहुत अच्छी तरह से नहीं करते हैं। लेकिन यह वास्तव में एक "सी" समाधान नहीं है।

कुछ जो मैं अक्सर करता हूं वह वक्र-फिटिंग सॉफ़्टवेयर का उपयोग करता है जो अनुमान लगाने के लिए तेजी से अनुमानों के साथ कार्यों को प्रतिस्थापित करता है। कभी-कभी LUTs गणनाओं का एक समूह करने से भी तेज़ होते हैं, लेकिन जितनी बार वे होते थे उतनी बार नहीं।

1

इस अध्याय को देखें, It’s a plain Wonderful Life एब्रैश द्वारा (यह लगभग 5 पृष्ठ है: प्रत्येक स्क्रीन के नीचे 'अगला' पर क्लिक करें)।

सारांश (लेख से कुछ उद्धरण):

  • टेबल पर ही आधारित जादू (विशाल लुकअप तालिका और अविश्वसनीय राज्य मशीन)
  • प्रदर्शन प्रोग्रामिंग करने के लिए एक दृष्टिकोण है कि एक अधिक कुशल, कसकर एकीकृत स्तर पर चल रही है की तुलना में आप कभी भी फिर से
  • प्रयास
1

की आश्चर्यजनक अर्थव्यवस्था दिखाई दें सी कोड प्रदर्शन के लिए कोई लेना देना नहीं अपरंपरागत बाईं है। सभी तकनीकों को "रूढ़िवादी" किया गया है।

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

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

आईए 64 जैसे कुछ समानांतर आर्किटेक्चर पर यह एक लूप को अंत तक सभी तरह से अनलॉक करने के लिए तेज़ हो सकता है। इसका एक उदाहरण सी स्ट्रिंग फ़ंक्शंस से परहेज कर रहा है। स्ट्रिंग सरणी को शून्य करने के लिए मेमसेट का उपयोग करें, स्ट्रिंग और memcmp सेट करने के लिए memcpy को पूरे सरणी की तुलना किसी अन्य समान सरणी के विरुद्ध करने के लिए करें। यह 64-बिट लोड का उपयोग कर सकता है, शून्य टर्मिनेटर के लिए कभी भी जांच नहीं करनी चाहिए और 64 या 128 के "छोटे" सरणी आकार का उपयोग करते समय लूप या शाखा को अनुकूलित नहीं किया जा सकता है। Memxxx() फ़ंक्शन आमतौर पर कंपाइलर निर्मित होते हैं- इन्स और बहुत अनुकूलित।

2

मैं "एक्स, वाई, या जेड करने का प्रयास करें" फ़ॉर्म के बहुत सारे जवाब सुनता हूं, लेकिन यह कहने की तरह है "सुनें, एक मछली लें, और एक दिन के लिए अच्छी तरह खाएं"।

प्रदर्शन की समस्याओं के लिए मैं आपको मछली कैसे सिखाऊंगा। जो लोग "प्रोफाइल फर्स्ट" कहते हैं, वे सही रास्ते पर हैं लेकिन (आईएमएचओ) बहुत डरावनी हैं।

Here's an example of aggressive performance tuning.

Here's a short explanation of why it works.

Here's a long explanation of why it works.

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

2

दाथन के उत्तर के भीतर ऊपर बिंदु 3 के लिए, स्वैपिंग का एक और तरीका, आप xor का उपयोग करके अपरंपरागत तरीके से चर को स्वैप कर सकते हैं।

 
int = 3, y = 4; 
x = x^y; 
y = y^x; 
x = x^y; 

अब एक्स और वाई बदल दिए गए हैं! :)

एक और बात, जब आप 2 के साथ कुछ विभाजित कर रहे हैं, तो शिफ्ट दाएं ऑपरेटर का उपयोग करना बेहतर होता है। 2 से गुणा करने के लिए कहा जा सकता है, शिफ्ट छोड़ दिया।

पुराने बोर्लैंड सी कंपाइलर में, _stklen संपत्ति थी जिसे आप स्टैक आकार और कोड को कम करने के लिए असाइन कर सकते हैं। मैंने आजकल ऐसा कुछ नहीं देखा है क्योंकि संकलक प्रौद्योगिकी के बाद से उन्नत है।

मॉलोक का उपयोग करते समय, कॉलक के बजाय बेहतर होगा क्योंकि यह स्मृति को शून्य पर प्रारंभ करता है।

if/else कथन के बजाय टर्नरी ऑपरेटर का उपयोग स्पष्ट रूप से तेज़ है, मुझे लगता है कि कंपाइलर लेखकों को मशीन कोड जनरेशन के संबंध में और अधिक स्मार्ट मिल गया है। मैं बस उस संबंध में उस सबूत प्रदान नहीं कर सकता, लेकिन यह तब सच था जब बोर्लैंड सी 3.01 ने रोस्ट पर शासन किया था।

असेंबली दिनचर्या के साथ कोड को रेखांकित करना।

मुझे यह प्रश्न विषय पसंद है क्योंकि यह मुझे पुराने दिनों की याद दिलाता है जब स्मृति कीमती थी और एक क्वार्ट पॉट में एक पिंट निचोड़ने के लिए और x86 कोड की होकस पॉकस चाल का उपयोग किया जाता था। इस प्रश्न को पोस्ट करने के लिए धन्यवाद श्रीडेटाबेस।

देखभाल करें, टॉम।

+1

मुझे यह भी उल्लेख करना चाहिए कि सरणी से निपटने पर, * (some_array + n) का उपयोग करके ऐसा करना तेज़ है जब आपने char some_array [50] घोषित किया है ... लेकिन अब यह कंपाइलर तकनीक के संबंध में अब अप्रासंगिक हो सकता है ...;) – t0mm13b