2016-02-02 23 views
7

मैं हॉटस्पॉट कोड है जो एक तंग पाश में चलता है:बचना पुनरावृत्ति/पाश unswitching

for (i = 0; i < big; i++) 
{ 
    if (condition1) { 
     do1(); 
    } else if (condition2) { 
     do2(); 
    } else { 
     do3(); 
    } 
    // Shared code goes here 
    // More shared code goes here 
} 

condition1 के बाद से और condition2 अपरिवर्तनीय हैं, मैं

if (condition1) { 
    for (i = 0; i < big; i++) 
    { 
     do1(); 
     // Shared code goes here 
     // More shared code goes here 
    } 
} else if (condition 2) { 
    for (i = 0; i < big; i++) 
    { 
     do2(); 
     // Shared code goes here 
     // More shared code goes here 
    } 
} else { 
    for (i = 0; i < big; i++) 
    { 
     do3(); 
     // Shared code goes here 
     // More shared code goes here 
    } 
} 

के पाश unswitched यह काफी बेहतर चलाता है, लेकिन मुझे आश्चर्य है कि खुद को दोहराए बिना ऐसा करने का एक चालाक तरीका है?

+0

शायद आप फ़ंक्शन पॉइंटर का उपयोग कर सकते हैं। शर्तों के आधार पर सेट करें, फिर उस एकल लूप के अंदर उपयोग करें। –

+0

क्या स्थिति 1 और condition2 संकलित समय पर ज्ञात हैं? – Straw1239

+0

@ स्ट्रॉ 1239: नहीं, जब भी फ़ंक्शन कहा जाता है तो वे अलग-अलग हो सकते हैं। – Charles

उत्तर

4

एक और, संभवतः थोड़ा और अधिक कुशल विकल्प का उपयोग करने के लिए है आपके लिए कोड बनाने के लिए एक मैक्रो:

#define DO_N(name, ...) for(int i = 0; i < big; i++){name(__VA_ARGS__);/*shared code*/} 

if (condition1) { 
    DO_N(do1, .../*arguments here*/) 
} else if (condition 2) { 
    DO_N(do2, ...) 
} else { 
    DO_N(do3, ...) 
} 

#undef DO_N 

यह बदसूरत है, लेकिन मुझे लगता है कि यह वही करता है जो आप चाहते हैं, और एक फ़ंक्शन पॉइंटर नहीं कहां रेखांकित कर सकता है।

इसके अतिरिक्त, आप अपने साझा कोड को एक अलग मैक्रो या फ़ंक्शन में रखने के लिए इसे और अधिक पठनीय पाते हैं।

+0

देखें [मेरी दूसरी टिप्पणी] (http://stackoverflow.com/questions/35161175/avoiding-repetition-loop-unswitching#comment58041402_35161313), जहां फ़ंक्शन पॉइंटर्स के माध्यम से कॉल (संभावित रूप से) रेखांकित हैं। निष्पादन निष्कर्षों पर आने से पहले यह मापने और जुड़ाव के साथ खेलना उचित है। – chris

+0

@ क्रिसिस मैंने देखा, और यह जानना अच्छा है कि कंपाइलर्स उस पर अच्छे हैं। मुझे यकीन नहीं था, इसलिए मैंने कहा "शायद"। – Straw1239

+0

हाँ, मैं निश्चित रूप से यह मानने से सावधान रहूंगा कि वे * आसानी से आसानी से रेखांकित किए जाएंगे। मेरे ज्ञान के लिए, फ़ंक्शन पॉइंटर्स बहुत अधिक हिट-एंड-मिस हैं, और ऐसा लगता है कि जीसीसी को थोड़ा सा प्रोडिंग की आवश्यकता है, उस बिंदु पर जहां यह पूरी तरह से फ़ंक्शन को खत्म कर सकता है। – chris

3

मुझे लगता है कि आप एक समारोह सूचक और कुछ समारोह foo() घोषणा कर सकते हैं:

typedef void (*fp)(void); 

void foo(int big, fp f) { 
    for (int i = 0; i < big; ++i) { 
     f(); 
     // Shared code goes here 
     // More shared code goes her 
    } 
} 

फिर कुछ इस तरह के लिए अपना कोड बदलें:

if (condition1) { 
    foo(big, do1); 
} else if (condition2) { 
    foo(big, do2); 
} else { 
    foo(big, do3); 
} 
+0

हां, यह एक अच्छा विचार है। लेकिन (क्षमा करें!) मैं यह उल्लेख करना भूल गया था कि मेरे कोड 'do1',' do2', और 'do3' में अलग-अलग हस्ताक्षर हैं। – Charles

+0

@ चार्ल्स हम्म, इस मामले में आपको एक और समाधान की आवश्यकता है ... –

+2

@ चार्ल्स, चूंकि 'do1(); do2(); do3(); 'पोस्ट में सभी एक ही तर्क (कोई नहीं) लेते हैं, यह उत्तर अच्छी तरह से इस पोस्ट का जवाब देता है। शायद आपके अतिरिक्त प्रतिबंधों के साथ एक और पोस्ट करें। – chux

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