2012-08-01 12 views
5

से बचने के लिए मूल्य मेरे पास एक ऐसी स्थिति है जहां प्रदर्शन बेहद महत्वपूर्ण है। मेरे एल्गोरिदम के मूल में एक विधि है जो दो double प्राइमेटिव के साथ कुछ मूल गणना करता है। इस विधि को एल्गोरिदम के प्रति रन दस मिलियन बार कहा जाता है।जावा आईईईई 64-बिट 754 डबल,

कोड इस तरह कुछ दिखता है;

public int compare(double xA, double xB, double yA, double yB); 

    double x = xA * xB; 
    double y = yA * yB; 

    double diff = x - y; 

    return (diff < 0.0 ? -1 : (diff > 0.0 ? 1 : 0)); 

} 

मापदंडों xA और yA एक सेट से उनके मूल्यों ले। इस सेट को कोड में tweaked किया जा सकता है। मैं सेट में रखे गए मानों के आधार पर विशाल (लगभग डबल) प्रदर्शन अंतर देख रहा हूं। ऐसा लगता है कि यदि सेट में 0.1 या 0.3 है, तो प्रदर्शन में एक बड़ी हिट होती है। 0.5 के गुणकों को सेट को रखने से सर्वश्रेष्ठ प्रदर्शन मिलता है।

क्या संकलक x * 0.5 को x >> 1 आदि के रूप में अनुकूलित कर रहा है? या ऐसा इसलिए है क्योंकि 0.1 बाइनरी में परिभाषित नहीं किया जा सकता है?

मैं इस स्थिति को थोड़ा बेहतर समझना चाहता हूं ताकि मैं इसे अनुकूलित कर सकूं। मुझे लगता है कि यह काफी कठिन समस्या हो सकती है जब तक कि कोई वास्तव में जानता है कि कैसे जावैक और जेवीएम (हमारे मामले में हॉटस्पॉट) डबल गुणा को संभालता है।

+0

क्या आप वाकई प्रदर्शन अंतर इस दिनचर्या में सीधे और नहीं पैदा कर रहा विभिन्न परिणामों वापस करने XA और फिर से बदल रहा है, इस प्रकार से बदल रहा है कि इस दिनचर्या रिटर्न के बाद मार डाला जाता है का परिणाम है कर रहे हैं? –

+0

आप उस लाइन को हटाकर और रिटर्न को 0 रिटर्न एक्स वाई के साथ बदलकर घटाकर खत्म कर सकते हैं? 1: 0; '। –

+0

यदि उपलब्ध ट्वीविंग उस बिंदु तक फैली हुई है जो xA और yA के लिए पी और क्यू मानता है तो उसे पी/क्यू और 1 द्वारा प्रतिस्थापित किया जा सकता है, फिर एक गुणा को हटाया जा सकता है, जिससे 'डबल x = xA * xB; डबल वाई = वाईबी; '(सामान्य फ़्लोटिंग-पॉइंट राउंडिंग मुद्दों के अधीन)। –

उत्तर

1

बस एक जोड़ी कुछ विचार:

  • तो मान 0.5 के कई हैं, तो mantissa में कुछ महत्वपूर्ण बिट हो जाएगा, तो यह संभव है कि गुणा कम मंडलियों लेता है। गुणा के लिए असल में महत्वपूर्ण बिट्स एक मुद्दा प्रतीत नहीं होता है, क्योंकि आधुनिक प्रोसेसर डबल के लिए केवल दो चक्र लेते हैं (जैसा कि Floating point division vs floating point multiplication में बताया गया है)।

    उदा। मुझे लगता है कि 0.5, 1, 2, 4, आदि के साथ मंटिसा सभी शून्य हो जाएगा (पहला "1" अंतर्निहित होने के लिए उत्सर्जित है)। .75, 1.5, 3 आदि के लिए, यह m.bb में "1" होगा। सभी शून्यों के बाद। जबकि 0.1 प्रतिनिधित्व के लिए सभी महत्वपूर्ण परिशुद्धता का उपयोग करेगा, और फिर भी एक छोटी सी त्रुटि होगी।

  • परिणाम के बारे में लौटा: क्या Math.signum() के साथ कोई समस्या है? मेरा मतलब है, हो सकता है यह एक ही करना होगा:

    return Math.signum(x-y); 
    
  • तो precission सर्वोपरि नहीं है, आप एक precission (नाव) उपयोग करने पर विचार हो सकता है। (हालांकि अगर इसका मतलब है कि आप दोबारा से आगे और पीछे परिवर्तित होने जा रहे हैं, तो यह इसके लायक नहीं हो सकता है)।

+1

यप साइनम काम करेगा, लेकिन इसका मतलब वापसी के लिए int कास्ट होगा, इस कारण से मैंने इसे टाला। – lynks

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