2012-03-13 21 views
15

क्या कोई विशेषता है जिसे मैं संकलक को बताने के लिए उपयोग कर सकता हूं कि एक विधि को हमेशा अनुकूलित किया जाना चाहिए, भले ही वैश्विक /o+ कंपाइलर स्विच सेट न हो?क्या मैं संकलक को एक विशिष्ट विधि को अनुकूलित करने के लिए मजबूर कर सकता हूं?

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


संपादित करें: गैर अनुकूलन नहीं है जो मुझे परेशान बारे में अधिक जानकारी ...

के भाज्य समारोह के निम्नलिखित कार्यान्वयन पर ध्यान दें:

static long FactorialRec(int n, long acc) 
{ 
    if (n == 0) 
     return acc; 
    return FactorialRec(n - 1, acc * n); 
} 

(नोट: मैं वहाँ पता फैक्टोरियल की गणना करने के बेहतर तरीके हैं, यह सिर्फ एक उदाहरण है)

आईएल अनुकूलन के साथ जेनरेट किया गया I काफी सरल है:

IL_0000: ldarg.0  
IL_0001: brtrue.s IL_0005 
IL_0003: ldarg.1  
IL_0004: ret   
IL_0005: ldarg.0  
IL_0006: ldc.i4.1  
IL_0007: sub   
IL_0008: ldarg.1  
IL_0009: ldarg.0  
IL_000A: conv.i8  
IL_000B: mul   
IL_000C: call  UserQuery.FactorialRec 
IL_0011: ret   

लेकिन unoptimized संस्करण काफी अलग

IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldc.i4.0  
IL_0003: ceq   
IL_0005: ldc.i4.0  
IL_0006: ceq   
IL_0008: stloc.1  
IL_0009: ldloc.1  
IL_000A: brtrue.s IL_0010 
IL_000C: ldarg.1  
IL_000D: stloc.0  
IL_000E: br.s  IL_001F 
IL_0010: ldarg.0  
IL_0011: ldc.i4.1  
IL_0012: sub   
IL_0013: ldarg.1  
IL_0014: ldarg.0  
IL_0015: conv.i8  
IL_0016: mul   
IL_0017: call  UserQuery.FactorialRec 
IL_001C: stloc.0  
IL_001D: br.s  IL_001F 
IL_001F: ldloc.0  
IL_0020: ret   

यह केवल एक ही निकास बिंदु के लिए डिज़ाइन किया गया है अंत में है। वापसी का मूल्य स्थानीय चर में संग्रहीत किया जाता है।

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

+1

AFAIK, नहीं - यह संभव नहीं है –

+1

जेआईटी कंपाइलर हमेशा हर विधि को अनुकूलित करेगा। – Steven

+0

@Steven, अगर आप इसे नहीं बताते हैं (उदा। 'MethodImplAttribute'' में 'NoOptimization' ध्वज के साथ)। लेकिन वैसे भी, मेरा प्रश्न संकलक अनुकूलन के बारे में है, जेआईटी अनुकूलन नहीं, क्योंकि मुझे उत्पन्न आईएल कोड में रूचि है। –

उत्तर

2

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

जहां तक ​​मूल मुद्दा है, चूंकि एमएसआईएल एक स्टैक आधारित भाषा है। और चश्मा ret कथन पर स्टैक स्टेटस की गारंटी देते हैं, आप 100% सुनिश्चित कर सकते हैं कि आप बिना किसी समस्या के पूंछ उपसर्ग जोड़ सकते हैं। हालांकि, वास्तव में किसी भी लाभ को जोड़ने की संभावना नहीं है क्योंकि मैंने वास्तव में जेआईटी को वास्तव में अंततः जब्त कोड को अनुकूलित करने के लिए पूंछ उपसर्ग का उपयोग नहीं किया है।

+0

डाउनवॉटर देखभाल क्या गलत है यह इंगित करने के लिए? –

+0

संबंधित: http://stackoverflow.com/questions/491376 - स्पष्ट रूप से '.tail' को x64 में अनुकूलित किया गया है लेकिन x86 नहीं –

0

क्या वैसे भी आप Microsoft.CSharp.CSharpCodeProvider का उपयोग कर गतिशील रूप से मूल विधि कोड उत्पन्न कर सकते हैं?

यदि आप विधि संकलन को नियंत्रित करते हैं, तो आप CompilerOptions का उपयोग करके कंपाइलर को कॉल करते समय विकल्पों को सेट कर सकते हैं।

+0

को उड़ा देगा जो इससे मदद नहीं करेगा; मैं कोड को गतिशील रूप से उत्पन्न नहीं करना चाहता (मूल कोड का मतलब नहीं) –

0

आप कभी भी यह सुनिश्चित नहीं कर सकते कि आपको पूंछ कॉल अनुकूलन मिल जाए, जब तक आप सी # का उपयोग न करें।

विशेष रूप से call ... ret के साथ भी जिटर एक पूंछ कॉल की गारंटी नहीं देता है। तो पूंछ कॉल अनुकूलन (स्टैक-ओवरफ्लो से बचने के लिए) पर निर्भर आईएमओ सी # कोड बस टूटा हुआ है। सी # पूंछ कॉल अनुकूलन में पूरी तरह से एक प्रदर्शन अनुकूलन है।

ऐसी भाषा का उपयोग करें जहां पूंछ कॉल विश्वसनीय रूप से उत्सर्जित हों, या अपनी विधि को फिर से लिखें ताकि उसे पूंछ की आवश्यकता न हो।

+0

मुझे पता है सी # पूंछ कॉल के लिए उपयुक्त नहीं है, मैं बस अवधारणा का सबूत कर रहा था ... चिंता मत करो, मैं नहीं करता उत्पादन कोड में इसका उपयोग करना चाहते हैं;) –

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

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