2011-03-04 9 views
7

के साथ सर्वश्रेष्ठ अभ्यास मैं एक एन छवि प्रसंस्करण लाइब्रेरी पर काम कर रहा हूं जो ओपनसीवी, हल्कॉन, ... को बढ़ाता है। पुस्तकालय .NET Framework 3.5 के साथ होना चाहिए और चूंकि .NET के साथ मेरे अनुभव सीमित हैं, इसलिए मैं प्रदर्शन के संबंध में कुछ प्रश्न पूछना चाहता हूं।Math.Pow

मुझे कुछ विशिष्ट चीजों का सामना करना पड़ा है जो मैं स्वयं को सही तरीके से समझा नहीं सकता हूं और आपसे पूछना चाहते हैं) क्यों और बी) मामलों से निपटने का सबसे अच्छा अभ्यास क्या है।

मेरा पहला सवाल Math.pow के बारे में है। मुझे पहले से ही स्टैक ओवरफ्लो पर कुछ जवाब मिल गए हैं जो इसे काफी अच्छी तरह बताते हैं (ए) लेकिन इस बारे में क्या नहीं करना है (बी)। मेरे बेंचमार्क कार्यक्रम लगता है कि यह

Stopwatch watch = new Stopwatch(); // from the Diagnostics class 
watch.Start(); 
for (int i = 0; i < 1000000; i++) 
    double result = Math.Pow(4,7) // the function call 
watch.Stop() 

परिणाम बहुत अच्छा है (~ अपने कंप्यूटर पर 300 मि.से) नहीं था (10 बार परीक्षण मैं चलने तथा औसत मूल्य calcuated)।

मेरा पहला विचार गीलेर को जांचना था क्योंकि यह एक स्थिर कार्य है। इसलिए मैं के माध्यम से अपने ही वर्ग

class MyMath 
{ 
    public static double Pow (double x, double y) //Using some expensive functions to calculate the power 
    { 
     return Math.Exp(Math.Log(x) * y); 
    } 

    public static double PowLoop (double x, int y) // Using Loop 
    { 
     double res = x; 
     for(int i = 1; i < y; i++) 
      res *= x; 
     return res; 
    } 

    public static double Pow7 (double x)   // Using inline calls 
    { 
     return x * x * x * x * x * x * x; 
    } 
} 

अगर मैं Math.Pow (4,7) की जगह लेंगे तीसरी बात मैं जाँच थे सीधे लागू किया 4 * 4 * 4 * 4 * 4 * 4 * 4। पाउ के लिए गणित का उपयोग न करें:

परिणाम (10 परीक्षण से बाहर औसत चलाता है)

300 ms Math.Pow(4,7) 
356 ms MyMath.Pow(4,7) //gives wrong rounded results 
264 ms MyMath.PowLoop(4,7) 
92 ms MyMath.Pow7(4) 
16 ms 4*4*4*4*4*4*4 

अब मेरी स्थिति अब इस तरह मूल रूप से है। मेरी एकमात्र समस्या यह है कि ... क्या मुझे वास्तव में अपनी खुद की गणित कक्षा को लागू करना है? यह किसी भी तरह से बिजली समारोह के लिए अपनी कक्षा को लागू करने के लिए अप्रभावी लगता है। (बीटीडब्ल्यू। पॉवेलूप और पॉव 7 रिलीज में तेजी से ~ 25% की वृद्धि करते हैं जबकि मैथ.पॉव नहीं है)।

तो मेरा अंतिम सवाल

हैं क) मैं गलत करता है, तो मैं सभी (लेकिन अंशों शायद) (जो मुझे किसी भी तरह उदास कर देता है के लिए) पर Math.Pow का उपयोग नहीं होता हूँ।

बी) यदि आपके पास अनुकूलित करने के लिए कोड है, तो क्या आप वास्तव में ऐसे सभी गणितीय परिचालनों को सीधे लिख रहे हैं?

ग) वहाँ शायद पहले से ही एक तेजी से (खुला स्रोत ^^) गणितीय क्रियाओं

घ) मेरे सवाल के स्रोत के लिए पुस्तकालय है मूल रूप से है: मैं मान लिया है कि .नेट फ्रेमवर्क खुद को पहले से ही बहुत अनुकूलित प्रदान करता है इस तरह के बुनियादी परिचालनों के लिए कोड/संकलन परिणाम - क्या यह गणित-वर्ग या हैंडलिंग सरणी हो और मैं थोड़ा आश्चर्यचकित था कि मुझे अपना कोड लिखकर कितना लाभ मिलेगा। क्या सी # में देखने के लिए कुछ अन्य, सामान्य "फ़ील्ड" या कुछ और है जहां मैं सीधे सी # पर भरोसा नहीं कर सकता।

+6

मुझे लगता है कि 4 * 4 * 4 * 4 * 4 * 4 * 4 का संकलन समय पर मूल्यांकन किया जाएगा, इसलिए यह बहुत तेज है। – Nick

+0

मुझे लगता है कि ज्यादातर लोगों के लिए 100ms या तो एक बड़ा सौदा नहीं है। सी # अक्सर ज्यादातर लोगों से ऐसे अनुप्रयोगों के लिए पहली पसंद नहीं है। – Ian

+1

क्या आपने बड़ी संख्या में परीक्षण किया था? मुझे लगता है कि Math.Pow को बड़े एक्सपोनेंट्स के लिए अनुकूलित किया गया है, और यह सामान करता है: x^7 == x^{3 + 3 + 1} == {x^3 + x^3 x}, जिसका अर्थ यह चल रहा है आदेश rougly ओ (लॉग (एन)) है, जबकि आपका समाधान ओ (एन) है, और शायद बड़े घाटे के लिए बहुत धीमी होगी। – markijbema

उत्तर

0

जब आप कोड की एक पंक्ति के लाखों पुनरावृत्तियों के बारे में बात कर रहे हैं तो स्पष्ट रूप से हर छोटी जानकारी में कोई फर्क पड़ता है।

Math.Pow() एक फ़ंक्शन कॉल है जो आपके मैन्युअल 4 * 4 ... * 4 उदाहरण से काफी धीमा होगा।

अपनी खुद की कक्षा को अपने संदिग्ध के रूप में न लिखें, आप मानक गणित वर्ग की तुलना में कुछ भी अधिक अनुकूलित करने में सक्षम होंगे।

1

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

दूसरा, जैसा कि आपने स्वयं कहा है, Math.Pow वास्तविकताओं को संभाल सकता है। यह एक साधारण पाश की तुलना में एक बहुत अधिक जटिल एल्गोरिदम का उपयोग करता है। कोई आश्चर्य नहीं कि यह बस लूपिंग से धीमा है। यदि आप लूप से छुटकारा पा लेते हैं और केवल एन गुणा करते हैं, तो आप लूप को स्थापित करने के ऊपरी हिस्से को भी काट रहे हैं - इस प्रकार इसे तेज़ी से बनाते हैं। लेकिन यदि आप लूप का उपयोग नहीं करते हैं, तो आपको पहले से एक्सपोनेंट का मान पता होना चाहिए - इसे रनटाइम पर आपूर्ति नहीं की जा सकती है।

मुझे सच में यकीन नहीं है कि क्यों Math.Exp और Math.Log तेज है। लेकिन यदि आप Math.Log का उपयोग करते हैं, तो आपको नकारात्मक मानों की शक्ति नहीं मिल सकती है।

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

सवाल यह है कि आपको खुद से पूछना है कि यह इसके लायक है या नहीं। Math.Pow वास्तव में आपके प्रोग्राम को धीमा कर रहा है? और किसी भी मामले में, Math.Pow पहले से ही आपकी भाषा के साथ बंडल किया गया है वह अक्सर सबसे तेज़ या बहुत करीब है। यदि आप वास्तव में एक वैकल्पिक कार्यान्वयन करना चाहते हैं जो वास्तव में सामान्य उद्देश्य है (यानी केवल पूर्णांक, सकारात्मक मान, आदि तक ही सीमित नहीं है), तो आप शायद उसी कार्यान्वयन में उपयोग किए गए उसी एल्गोरिदम का उपयोग कर समाप्त कर देंगे।

+1

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

+0

@markijbema: यही कारण है कि मैंने अपने जवाब में "सामान्य उद्देश्य" शब्द का उपयोग किया। यदि आप डेटा के बारे में अतिरिक्त धारणाएं बना सकते हैं (उदा। वे हमेशा पूर्णांक होंगे, या किसी दिए गए सीमा के भीतर होंगे), निश्चित रूप से आप ऐसा कुछ कर सकते हैं जो इसका उपयोग करके अनुकूलित करता है (उदा। क्विकॉर्ट के बजाय गिनती सॉर्ट करें)। सामान्य उद्देश्य कार्यों के लिए, मेरे उत्तर का यह पूरा बिंदु है, पुस्तकालय से मेल खाना मुश्किल है। – MAK

4

दो बातें ध्यान में रखना:

  1. आप शायद don't need to optimise कोड के इस बिट। आपने अभी तक एक सेकंड से भी कम समय में फ़ंक्शन में दस लाख कॉल किए हैं। क्या यह वास्तव में आपके कार्यक्रम में बड़ी समस्याएं पैदा करेगा?

  2. Math.Pow शायद वैसे भी काफी अनुकूल है। अनुमान में, यह निम्न स्तर की भाषा में लिखी गई उचित संख्या पुस्तकालय को बुलाएगा, जिसका अर्थ है कि आपको परिमाण बढ़ने के आदेश की अपेक्षा नहीं करनी चाहिए।

  3. संख्यात्मक प्रोग्रामिंग आपके विचार से कठिन है। यहां तक ​​कि एल्गोरिदम जो आपको लगता है कि आप गणना कैसे करते हैं, इस तरह की गणना नहीं की जाती है। उदाहरण के लिए, जब आप माध्य की गणना करते हैं, तो आपको संख्याओं को जोड़ना नहीं चाहिए और आपके पास कितनी संख्याएं हैं। (आधुनिक numerics पुस्तकालयों एक नियमित दो पास का उपयोग चल बिन्दु त्रुटियों के लिए सही करने के लिए।)

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

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