डिनराइज़्ड फ़्लोटिंग-पॉइंट की दुनिया में आपका स्वागत है ! वे प्रदर्शन पर कहर बरपा सकते हैं !!!
फ्लोटिंग पॉइंट प्रतिनिधित्व से शून्य के करीब कुछ अतिरिक्त मान प्राप्त करने के लिए असामान्य (या सबनॉर्मल) नंबर एक हैक की तरह होते हैं। सामान्यीकृत फ्लोटिंग-पॉइंट की तुलना में डिनराइज्ड फ्लोटिंग-पॉइंट पर ऑपरेशन दसियों बार धीमा हो सकता है । ऐसा इसलिए है क्योंकि कई प्रोसेसर सीधे उन्हें संभाल नहीं सकते हैं और उन्हें ट्रैप और माइक्रोकोड का उपयोग करके हल करना चाहिए।
यदि आप 10,000 पुनरावृत्तियों के बाद संख्याओं का प्रिंट आउट करते हैं, तो आप देखेंगे कि उन्होंने अलग-अलग मानों में कनवर्ट किया है 0
या नहीं, इसके आधार पर 0.1
उपयोग किया जाता है।
यहाँ परीक्षण कोड x64 पर संकलित किया गया है:
int main() {
double start = omp_get_wtime();
const float x[16]={1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0,2.1,2.2,2.3,2.4,2.5,2.6};
const float z[16]={1.123,1.234,1.345,156.467,1.578,1.689,1.790,1.812,1.923,2.034,2.145,2.256,2.367,2.478,2.589,2.690};
float y[16];
for(int i=0;i<16;i++)
{
y[i]=x[i];
}
for(int j=0;j<9000000;j++)
{
for(int i=0;i<16;i++)
{
y[i]*=x[i];
y[i]/=z[i];
#ifdef FLOATING
y[i]=y[i]+0.1f;
y[i]=y[i]-0.1f;
#else
y[i]=y[i]+0;
y[i]=y[i]-0;
#endif
if (j > 10000)
cout << y[i] << " ";
}
if (j > 10000)
cout << endl;
}
double end = omp_get_wtime();
cout << end - start << endl;
system("pause");
return 0;
}
आउटपुट:
#define FLOATING
1.78814e-007 1.3411e-007 1.04308e-007 0 7.45058e-008 6.70552e-008 6.70552e-008 5.58794e-007 3.05474e-007 2.16067e-007 1.71363e-007 1.49012e-007 1.2666e-007 1.11759e-007 1.04308e-007 1.04308e-007
1.78814e-007 1.3411e-007 1.04308e-007 0 7.45058e-008 6.70552e-008 6.70552e-008 5.58794e-007 3.05474e-007 2.16067e-007 1.71363e-007 1.49012e-007 1.2666e-007 1.11759e-007 1.04308e-007 1.04308e-007
//#define FLOATING
6.30584e-044 3.92364e-044 3.08286e-044 0 1.82169e-044 1.54143e-044 2.10195e-044 2.46842e-029 7.56701e-044 4.06377e-044 3.92364e-044 3.22299e-044 3.08286e-044 2.66247e-044 2.66247e-044 2.24208e-044
6.30584e-044 3.92364e-044 3.08286e-044 0 1.82169e-044 1.54143e-044 2.10195e-044 2.45208e-029 7.56701e-044 4.06377e-044 3.92364e-044 3.22299e-044 3.08286e-044 2.66247e-044 2.66247e-044 2.24208e-044
ध्यान दें कि दूसरे रन में संख्या शून्य के बहुत करीब है।
सामान्यीकृत संख्याएं आमतौर पर दुर्लभ होती हैं और इस प्रकार अधिकांश प्रोसेसर उन्हें कुशलता से संभालने की कोशिश नहीं करते हैं।
यह प्रदर्शित करने के लिए कि यह हर किसी के लिए असमान संख्याओं के साथ है, अगर हम इसे कोड की शुरुआत में जोड़कर शून्य को फ्लश करते हैं:
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
तब वाला संस्करण 0
अब 10x धीमा नहीं है और वास्तव में तेज हो जाता है। (इसके लिए यह आवश्यक है कि कोड को एसएसई सक्षम के साथ संकलित किया जाए।)
इसका मतलब यह है कि इन अजीब कम सटीक लगभग-शून्य मानों का उपयोग करने के बजाय, हम इसके बजाय केवल गोल करते हैं।
समय: कोर i7 920 @ 3.5 GHz:
// Don't flush denormals to zero.
0.1f: 0.564067
0 : 26.7669
// Flush denormals to zero.
0.1f: 0.587117
0 : 0.341406
अंत में, इसका वास्तव में कोई लेना-देना नहीं है कि यह पूर्णांक है या फ्लोटिंग-पॉइंट है। 0
या 0.1f
परिवर्तित / दोनों छोरों का एक रजिस्टर के बाहर में संग्रहित है। ताकि प्रदर्शन पर कोई प्रभाव न पड़े।