मैं जावा में कुछ कोड लिख रहा हूं, जहां कुछ बिंदु पर, कार्यक्रम का प्रवाह दो अंतर चर, "एक" और "बी" द्वारा निर्धारित किया जाता है, गैर-शून्य हैं (ध्यान दें: ए और बी कभी नकारात्मक नहीं हैं, और) पूर्णांक अतिप्रवाह सीमा के भीतर कभी नहीं)।
मैं इसके साथ मूल्यांकन कर सकता हूं
if (a != 0 && b != 0) { /* Some code */ }
या वैकल्पिक रूप से
if (a*b != 0) { /* Some code */ }
क्योंकि मुझे उम्मीद है कि कोड के उस टुकड़े को प्रति बार लाखों बार चलाना होगा, मैं सोच रहा था कि कौन सा तेज होगा। मैंने एक विशाल यादृच्छिक रूप से उत्पन्न सरणी पर उनकी तुलना करके प्रयोग किया था, और मैं यह देखने के लिए भी उत्सुक था कि सरणी की स्पार्सिटी (डेटा का अंश = 0) परिणामों को कैसे प्रभावित करेगा:
long time;
final int len = 50000000;
int arbitrary = 0;
int[][] nums = new int[2][len];
for (double fraction = 0 ; fraction <= 0.9 ; fraction += 0.0078125) {
for(int i = 0 ; i < 2 ; i++) {
for(int j = 0 ; j < len ; j++) {
double random = Math.random();
if(random < fraction) nums[i][j] = 0;
else nums[i][j] = (int) (random*15 + 1);
}
}
time = System.currentTimeMillis();
for(int i = 0 ; i < len ; i++) {
if( /*insert nums[0][i]*nums[1][i]!=0 or nums[0][i]!=0 && nums[1][i]!=0*/ ) arbitrary++;
}
System.out.println(System.currentTimeMillis() - time);
}
और परिणाम बताते हैं कि यदि आप "ए" या "बी" की अपेक्षा करते हैं, तो a*b != 0
यह समय के ~ 3% से अधिक 0 के बराबर है, यह तेजी से होता है a!=0 && b!=0
:
मैं यह जानने के लिए उत्सुक हूं कि क्यों। क्या कोई प्रकाश डाल सकता है? क्या यह संकलक है या यह हार्डवेयर स्तर पर है?
संपादित करें: जिज्ञासा से बाहर ... अब जब मैंने शाखा की भविष्यवाणी के बारे में जाना, तो मैं सोच रहा था कि ओआर या बी के लिए एनालॉग तुलना क्या दिखाएगी गैर-शून्य:
हम उम्मीद के अनुसार शाखा भविष्यवाणी का एक ही प्रभाव देखते हैं, दिलचस्प है कि ग्राफ एक्स-एक्सिस के साथ कुछ हद तक फ़्लिप किया गया है।
अपडेट करें
1- मैंने !(a==0 || b==0)
विश्लेषण में जोड़ा कि क्या होता है।
2- मैंने शाखा भविष्यवाणी के बारे में जानने के बाद a != 0 || b != 0
, (a+b) != 0
और (a|b) != 0
जिज्ञासा से बाहर भी शामिल किया । लेकिन वे तार्किक रूप से अन्य अभिव्यक्तियों के समतुल्य नहीं होते हैं, क्योंकि सत्य होने के लिए केवल एक या बी को गैर-शून्य होने की आवश्यकता होती है, इसलिए उन्हें प्रसंस्करण दक्षता के लिए तुलना करने के लिए नहीं है।
3- मैंने उस वास्तविक बेंचमार्क को भी जोड़ा जो मैंने विश्लेषण के लिए उपयोग किया था, जो कि एक मनमाना इंट वैरिएबल है।
4- कुछ लोग भविष्यवाणी के a != 0 & b != 0
विपरीत शामिल करने का सुझाव दे रहे थे a != 0 && b != 0
, इस भविष्यवाणी के साथ कि यह अधिक निकटता से व्यवहार करेगा a*b != 0
क्योंकि हम शाखा पूर्वानुमान प्रभाव को हटा देंगे। मुझे नहीं पता था कि &
बूलियन चर के साथ इस्तेमाल किया जा सकता है, मुझे लगा कि यह केवल पूर्णांक के साथ द्विआधारी संचालन के लिए उपयोग किया गया था।
नोट: इस संदर्भ में कि मैं इस सब पर विचार कर रहा था, int overflow कोई समस्या नहीं है, लेकिन यह सामान्य संदर्भों में एक महत्वपूर्ण विचार है।
CPU: Intel Core i7-3610QM @ 2.3GHz
जावा संस्करण: 1.8.0_45
जावा (TM) एसई रनटाइम एनवायरनमेंट (बिल्ड 1.8.0_45-b14)
जावा हॉटस्पॉट (TM) 64-बिट सर्वर VM (बिल्ड 25.45-b02, मिश्रित मोड)
a != 0 & b != 0
।
a*b!=0
एक कम शाखा है
(1<<16) * (1<<16) == 0
अभी तक दोनों शून्य से अलग हैं।
a*b
शून्य अगर है एक की a
और b
शून्य है; a|b
दोनों हैं तो ही शून्य है।
if (!(a == 0 || b == 0))
? माइक्रोबेन्चमार्क बहुत ही अविश्वसनीय रूप से अविश्वसनीय हैं, यह वास्तव में औसत दर्जे का होने की संभावना नहीं है (~ 3% मेरे लिए त्रुटि के एक मार्जिन की तरह लगता है)।