2008-09-28 14 views
5

मैं बड़े बहु-मंद सरणियों पर छोरों के लिए उपयोग कर रहा हूँ के रूप में, किसी के लिए लूप तंत्र पर बचत ही सार्थक है।के लिए लूप तंत्र दक्षता सुझावों

तदनुसार, मैं कैसे इस भूमि के ऊपर कम करने के लिए कोई सुझाव के लिए देख रहा हूँ।

उदा। : int के बजाय uint का उपयोग करके गिनती करना और 0 = 0 के बजाय स्टॉप के रूप में 0 0 सीपीयू को कम काम करने की अनुमति देता है (यह एक बार सुना है, यह सुनिश्चित नहीं है कि यह हमेशा सत्य है)

+0

@monoxide से उत्तर देखें। यह भाषा अज्ञेयवादी टैग नहीं किया जाना चाहिए और मुझे लगता है कि अगर आपको पता है कि कौन सी भाषा/कंपाइलर वे अनुकूलित करने की कोशिश कर रहे हैं तो आपको बेहतर जवाब मिलेंगे। –

+0

सहमत हैं, ऑप्टिमाइज़ेशन भाषा विशिष्ट है, और जिस तरीके से आप सवाल करते हैं, वैसे ही आप एक विशेष मंच को लक्षित करने के लिए नीचे आते हैं (ओप टाइम्स अलग-अलग सीपीयू के लिए अलग-अलग होते हैं) – Oskar

+0

टैग की आवश्यकता है-स्पष्टीकरण – Sklivvz

उत्तर

4

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

कहा जा रहा है, आधुनिक CPUs पर अनलॉकिंग लूप से बहुत सावधान रहें। वे जितना कठिन हो उतना बेहतर होगा, वे कैश में फिट होंगे। पिछले साल मैंने एक उच्च प्रदर्शन अनुप्रयोग में काम किया था, मैंने सीधे लाइन कोड के बजाय लूप का उपयोग करके प्रदर्शन में काफी सुधार किया, और जितना संभव हो उतना कस कर उन्हें बढ़ाया। (हाँ, मैंने प्रोफाइल किया; सवाल में कार्य रन का 80% लिया।मैं भी ठेठ इनपुट से अधिक बार बेंचमार्क, तो मैं परिवर्तन में मदद की थी।)

इसके अलावा, करने वाला है कि कुशल कोड के पक्ष में विकसित करने में कोई बुराई नहीं है। सी ++ में, आप पहले से वेतन वृद्धि का उपयोग कर की आदत में मिलता है (++ i) के बजाय बाद वेतन वृद्धि (i ++) पाश चर बढ़ाने के लिए करना चाहिए। यह आमतौर पर कोई फर्क नहीं पड़ता, लेकिन एक महत्वपूर्ण अंतर कर सकता है, यह कोड को कम पठनीय या लिखने योग्य नहीं बनाता है, और चोट नहीं पहुंचाएगा।

12

एक महत्वपूर्ण सुझाव: जितना अधिक गणना करें जितना संभव हो बाहरी लूप। सभी कंपाइलर्स स्वचालित रूप से ऐसा नहीं कर सकते हैं। eample, बजाय के लिए:

for row = 0 to 999 
    for col = 0 to 999 
     cell[row*1000+col] = row * 7 + col 

उपयोग:

for row = 0 to 999 
    x = row * 1000 
    y = row * 7 
    for col = 0 to 999 
     cell[x+col] = y + col 
+0

हां, जो मेरी सलाह के साथ गूंजता है: मेक आंतरिक लूप तेजी से। इसका एक उदाहरण क्विक्सोर्ट है। –

1

अपने छोरों O (n^घ) जटिलता (घ = आयाम) होगा के रूप में, क्या वास्तव में मायने रखता है कि आप क्या पाश में डाल दिया है लूप खुद ही नहीं। लूप के अंदर एक अक्षम एल्गोरिदम के लाखों चक्रों से लूप ढांचे में कुछ चक्रों को अनुकूलित करना सिर्फ सांप का तेल है।

+0

मैंने ओ नोटेशन को तब तक उपयोगी नहीं पाया जब तक कि दो एल्गोरिदम की तुलना न हो। यह कहना समझ में आता है कि बबल सॉर्ट ओ (एन^2) है जबकि क्विक्सोर्ट ओ (एन एलजी एन) है। यह कभी कहने के लिए मुझे कभी समझ में नहीं आया कि ओ (एन^2) कुछ है, इसकी तुलना करने के समान कुछ भी। –

+0

पंडिताऊ होने के लिए: quicksort के बुनियादी कार्यान्वयन हे की औसत मामले जटिलता (एन एन लॉग इन करें) है, लेकिन अभी भी हे की सबसे खराब स्थिति जटिलता (एन^2) है। –

+0

हम एल्गोरिदम की तुलना करने के बारे में बात नहीं कर रहे हैं, Thorsten79 बस यह इंगित करना चाहता था कि लूप के लिए नेस्टेड n^d बार के क्रम पर गणना करने जा रहा है, और आंतरिक कोड की छोटीता लूप संरचना से अधिक महत्वपूर्ण है। – Karl

5

लूप-unrolling एक तरीका हो सकता है। यही कारण है:

for (i=0; i<N; i++) { 
    a[i]=...; 
} 

में परिवर्तित हो:

for (i=0; i<N; i+=4) { 
    a[i]=...; 
    a[i+1]=...; 
    a[i+2]=...; 
    a[i+3]=...; 
} 

आप विशेष हैंडलिंग की आवश्यकता होगी जब एन ऊपर के उदाहरण में 4 की एक बहु नहीं है।

+0

यह और अधिक कुशल बनाता है? खासकर उस मामले में जहां एन 4 से विभाजित नहीं है, और इसलिए यदि आप लूप के शीर्ष पर स्टेटमेंट चेक करते हैं तो आप अतिरिक्त परिचय दे रहे हैं? –

+0

यदि एन बड़ा है, तो बयानों के सापेक्ष ओवरहेड काफी छोटे हैं। (उन्हें लूप के बाहर ही रखा जाना चाहिए।) इसके अलावा, लूप द्वारा पेश किया गया ओवरहेड उदाहरण में (लगभग) 1/4 तक कम हो गया है। अनोलिंग केवल तभी समझ में आता है जब प्रत्येक तत्व के लिए किए गए ऑपरेशन त्वरित होते हैं। – SteinNorheim

+0

इससे कोई फर्क पड़ता है, हालांकि अधिकांश आत्म सम्मान करने वाले कंपाइलर्स पहले से ही ऐसा करेंगे! –

6

क्या आपने ओवरहेड मापा है? क्या आपको पता है कि लूप बनाम प्रोसेसिंग में कितना समय व्यतीत होता है। आपके आवेदन कोड को निष्पादित करने में कितना समय व्यतीत होता है? आपका लक्ष्य क्या है?

4

यह एक भाषा नास्तिक सवाल नहीं है, यह न केवल भाषा पर अत्यधिक निर्भर करता है, लेकिन यह भी संकलक। अधिकांश compilers मेरा मानना ​​है कि इन दोनों के समतुल्य रूप संकलन होगा:

for (int i = 0; i < 10; i++) { /* ... */ } 

int i = 0; 
while (i < 10) { 
    // ... 
    i++; 
} 

सबसे अधिक भाषाओं/compilers में, पाश के लिए बाद में, जबकि पाश के लिए बस वाक्यात्मक चीनी है। Foreach फिर से एक और सवाल है, और यह भाषा/कंपाइलर पर अत्यधिक निर्भर है कि यह कैसे लागू किया गया है, लेकिन यह आम तौर पर कम कुशल है कि लूप के लिए सामान्य। फिर से कितना और भाषा, संकलक निर्भर है।

आपकी सर्वश्रेष्ठ शर्त शायद थीम पर कई अलग-अलग विविधताओं के साथ कुछ बेंचमार्क चलाने के लिए होगी और देखें कि शीर्ष पर क्या आता है।

संपादित करें: इसके लिए suggestions here शायद आपको अधिक समय नहीं बल्कि पाश ही के बारे में चिंता की तुलना में बचत होगी।

3

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

9

अपने छोरों स्मृति में सन्निहित बनाने की कोशिश करें, यह कैश उपयोग अनुकूलित करेंगे। यही कारण है, यह मत करो जाता है:

for (int i = 0; i < m; i++) 
    for (j = 0; j < n; j++) 
     s += arr[j][i]; 
  • तो प्रसंस्करण छवियों, दो छोरों एक पाश के लिए पिक्सल पर एक सूचकांक के साथ परिवर्तित।
  • लूप न करें जो शून्य बार चलाएंगे, क्योंकि पाइपलाइन को एक लूप मानने के लिए अनुकूलित किया गया है, अंत के बजाय जारी रहेगा।
4

बीटीडब्लू, जब तक कि आपको पोस्ट-वृद्धि की आवश्यकता न हो, आपको हमेशा पूर्व-वृद्धि ऑपरेटर का उपयोग करना चाहिए। यह केवल मामूली अंतर है, लेकिन यह अधिक कुशल है।

आंतरिक इस अंतर है:

int postincrement(int &i)
{
int itmp = i;
i = i + 1;
return itmp;
}

  • पूर्व इंक:

    • पोस्ट वृद्धि

      i++;

      रूप में ही है rement

      ++i;

      रूप में ही है:

      int preincrement(int &i)
      {
      i = i + 1;
      return i;
      }

  • +0

    मुझे लगता है कि आप ++ i लिखना चाहते थे; –

    +0

    जब आप एक इंटेल को बढ़ा रहे हैं तो संकलक को अंतर को अनुकूलित करने की संभावना बहुत अधिक है। iterators से निपटने के दौरान यह अधिक प्रासंगिक है। – shoosh

    0

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

    0

    आपके प्रश्न का सही उत्तर देने के लिए पर्याप्त जानकारी नहीं है। आप अपने लूप के अंदर क्या कर रहे हो? क्या एक पुनरावृत्ति में गणना पिछले पुनरावृत्ति में गणना की गई मान पर निर्भर करती है। यदि नहीं, तो आप कम से कम एक दोहरे कोर प्रोसेसर मानते हुए, केवल 2 धागे का उपयोग करके अपना समय आधे में घटा सकते हैं।

    को देखने के लिए एक और बात है कि कैसे आप अपने डेटा तक पहुँच रहे हैं यदि आप बड़े सरणी प्रसंस्करण कर रहे हैं, अपने एल 1 निस्तब्धता से बचने के रूप में यह स्मृति में संग्रहित है सुनिश्चित करें कि आप डाटा को अनुक्रम का उपयोग करने के लिए,/एल 2 कैश प्रत्येक पुनरावृत्ति पर (इसे छोटे एल 1 कैशों पर पहले देखा गया, अंतर नाटकीय हो सकता है)।

    फिर से, मैं पहले लूप के अंदर क्या देखता हूं, जहां बाहरी लाभ (> 99%) बाहरी पाश नलसाजी की बजाय होगा।

    लेकिन फिर, यदि आपका लूप कोड I/O बाध्य है, तो अनुकूलन पर खर्च किए गए किसी भी समय बर्बाद हो जाता है।

    0

    एक और stackoverflow सवाल, how cache memory works के जवाब के बीच में कुछ प्रासंगिक जानकारी नहीं है। मैं Ulrich Drepper द्वारा कागज this जवाब विशेष रूप से उपयोगी में निर्दिष्ट पाया।

    1

    वैसे, क्या shortint के बजाय फॉर-लूप में उपयोग करना अच्छा है यदि Int16 क्षमता पर्याप्त होने की गारंटी है?

    +1

    अधिकांश आधुनिक कंप्यूटरों में 32 बिट ऑपरेशंस 16 बिट जितना तेज होगा। तो, जवाब नहीं है इससे कोई फर्क नहीं पड़ता। –

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