मेरे पास एक संख्यात्मक कोड है जो एक समीकरण f(x) = 0
हल करता है, जिसमें मुझे x
को p
पर x
उठाना है। मैं चीजों का एक समूह का उपयोग करके इसे हल करता हूं, लेकिन अंत में मेरे पास न्यूटन की विधि है। समाधान x = 1
के बराबर होता है, और इस प्रकार मेरी समस्याओं का कारण है। जब पुनरावृत्त समाधान 1
के करीब आता है, तो x = 1 + 1e-13
कहें, std::pow(x, p)
की गणना करने के लिए आवश्यक समय 100 के कारक द्वारा आसानी से बढ़ता है, जिससे मेरा कोड अनुपयोगी हो जाता है।बहुत धीमी std :: pow() बेस के लिए बहुत करीब 1
इस बात को चलाने वाली मशीन CentOS पर AMD64 (Opteron 6172) है, और कमांड है। इसी तरह का व्यवहार मेरी सभी मशीनों, सभी x64 पर दिखाई देता है। दस्तावेज here के रूप में, यह केवल मेरी समस्या नहीं है (यानी, कोई और भी pissed है), केवल x64 पर दिखाई देता है और केवल 1.0
के करीब दिखाई देता है। इसी तरह की चीज exp
होती है।
इस समस्या को हल करना मेरे लिए महत्वपूर्ण है। क्या किसी को पता है कि इस धीमेपन के आसपास जाने का कोई तरीका है?
संपादित करें: जॉन ने इंगित किया कि यह denormals के कारण है। सवाल यह है कि, इसे कैसे ठीक किया जाए? कोड GNU Octave
के भीतर उपयोग के लिए g++
के साथ संकलित C++ है। ऐसा प्रतीत होता है कि, हालांकि मैंने CXXFLAGS
को -mtune=native
और -ffast-math
शामिल करने के लिए सेट किया है, जो मदद नहीं कर रहा है और कोड धीरे-धीरे चलता है।
अब के लिए PSEUDO- समाधान: इस समस्या की परवाह करने वाले सभी लोगों के लिए, नीचे दिए गए समाधान व्यक्तिगत रूप से मेरे लिए काम नहीं करते थे। मुझे वास्तव में std::pow()
की सामान्य गति की आवश्यकता है, लेकिन x = 1
के आसपास आलसीता के बिना। मेरे लिए व्यक्तिगत रूप से समाधान निम्नलिखित हैक उपयोग करने के लिए है:
inline double mpow(double x, double p) __attribute__ ((const));
inline double mpow(double x, double p)
{
double y(x - 1.0);
return (std::abs(y) > 1e-4) ? (std::pow(x, p)) : (1.0 + p * y * (1.0 + (p - 1.0) * y * (0.5 + (1.0/6.0) * (p - 2.0) * y)));
}
बाध्य बदला जा सकता है, लेकिन -40 < पी < 40 के लिए त्रुटि 1e-11 के बारे में है, जो काफी अच्छा है से छोटा है। ओवरहेड जो मैंने पाया उससे कम है, इस प्रकार यह मेरे लिए मुद्दा हल करता है।
यह [सामान्य से कम संख्या] के साथ सामान्य प्रदर्शन की समस्याओं से संबंधित हो सकता (http://en.wikipedia.org/wiki/Denormal_number)। फ्लोटिंग पॉइंट मानों के साथ कंप्यूटेशंस 0 के बहुत करीब सामान्य से 100x धीमी हो सकती हैं। Http://stackoverflow.com/questions/9314534/why-does-changing-0-1f-to-0-slow-down-performance-by-10x देखें। –
अच्छा बिंदु। इस समाधान को हल करने के लिए कोई सुझाव? अगर वे काफी करीब हैं तो संख्याओं को ठीक से ठीक करें? –
@ जॉन कुगेलमैन: यदि आप लिंक पढ़ते हैं, तो ऐसा इसलिए होता है क्योंकि ग्लिबैक कुछ धीमे फ़ंक्शन का उपयोग करता है (नाम '__slowpow') जब कुछ इनपुट मान दिए जाते हैं। – interjay