दिलचस्प पोस्ट
एक। एपिसोड फ़ाइल क्या है ..? अनुरोध के लिए कोई प्रतिक्रिया प्राप्त होने पर क्या होता है? मैं फिर से कोशिश कर रहा हूँ कोड का एक सचित्र समारोह कॉल ग्राफ़ प्राप्त करने के लिए उपकरण अप्रमाणित स्ट्रिंग के सामान्य स्रोत गीथ रिमोट शाखा लाने के लिए स्क्रीनशॉट की आईओएस जांच जावा बाइटकोड में स्केल के गुण कैसे संकलित किए जाते हैं? Silverlight के साथ एक WP7 अनुप्रयोग में GIF प्रदर्शित करें सिंक्रनाइज़ एक एएसआईएनसी ऑपरेशन के लिए इंतजार कर रहा है, और क्यों रुको () प्रोग्राम को फ्रीज करता है यहाँ सी ++ में त्रिकोण अनुक्रम का उद्देश्य? AJAX का उपयोग करके PHP फ़ाइल से उत्तर प्राप्त करें कीप्रेस पढ़ने के लिए पायथन विधि? UIPageViewController स्क्रॉल संक्रमण शैली के साथ गलत पृष्ठ पर नेविगेट करता है मैं Xcode 4 पर कैसे कमजोर लिंक चौखटे? XElement के लिए लाइन नंबर यहां प्राप्त करें

क्यों 0.1f से 0 को 10x से नीचे प्रदर्शन धीमा कर देता है?

कोड का यह बिट क्यों है,

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]; y[i] = y[i] + 0.1f; // <-- y[i] = y[i] - 0.1f; // <-- } } 

निम्नलिखित बिट की तुलना में 10 गुना अधिक तेज चलाएं (जहां उल्लेख किया गया है के अलावा समान)?

 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]; y[i] = y[i] + 0; // <-- y[i] = y[i] - 0; // <-- } } 

दृश्य स्टूडियो 2010 SP1 के साथ संकलन करते समय (मैंने अन्य कंपाइलर्स के साथ परीक्षण नहीं किया है।)

वेब के समाधान से एकत्रित समाधान "क्यों 0.1f से 0 को 10x से नीचे प्रदर्शन धीमा कर देता है?"

Denormalized अस्थायी बिंदु की दुनिया में आपका स्वागत है! वे प्रदर्शन पर कहर बरपा सकते हैं !!!

फ्लोटिंग पॉइंट प्रस्तुति से शून्य के करीब कुछ अतिरिक्त मूल्य प्राप्त करने के लिए डायमंडल (या असामान्य) नंबर एक हैक हैं। अस्वीकृत फ़्लोटिंग-पॉइंट पर संचालन सामान्यीकृत फ्लोटिंग-पॉइंट से सैकड़ों गुना धीमी गति से हो सकता है। इसका कारण यह है कि कई प्रोसेसर उन्हें सीधे नहीं संभाल सकते हैं और उन्हें माइक्रोकोड का उपयोग करके उन्हें फंसाकर हल करना होगा।

अगर आप 10,000 पुनरावृत्तियों के बाद संख्या प्रिंट करते हैं, तो आप देखेंगे कि उन्होंने 0 या 0.1 का प्रयोग किया जाता है, इस पर निर्भर करते हुए अलग-अलग मानों में एकत्र किया है।

यहां एक्स 64 पर संकलित कोड है:

 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 

ध्यान दें कि दूसरे भाग में संख्या शून्य के बहुत करीब हैं।

Denormalized संख्या आम तौर पर दुर्लभ होते हैं और इस प्रकार अधिकांश प्रोसेसर उन्हें कुशलता से संभालने की कोशिश नहीं करते।


प्रदर्शित करने के लिए यह सब कुछ denormalized संख्या के साथ करना है, अगर हम denormals को कोड की शुरुआत करने के लिए इसे जोड़कर शून्य करने के लिए फ्लश :

 _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); 

फिर 0 साथ संस्करण अब 10x धीमा नहीं है और वास्तव में तेज़ हो जाता है। (यह आवश्यक है कि कोड एसएसई सक्षम के साथ संकलित किया जाए।)

इसका मतलब यह है कि इन अजीब कम सटीक लगभग-शून्य मानों का उपयोग करने के बजाय, हम केवल इसके बजाय शून्य पर गोल करते हैं।

समय: कोर i7 920 @ 3.5 गीगाहर्ट्ज़:

 // 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 को दोनों छोरों के बाहर एक रजिस्टर में कनवर्ट किया जाता है / संग्रहीत किया जाता है। इसलिए प्रदर्शन पर कोई प्रभाव नहीं पड़ता है

gcc का उपयोग करना और जनरेटेड असेंबली के लिए एक अंतर लागू करने से केवल यह अंतर उत्पन्न होता है:

 73c68,69 < movss LCPI1_0(%rip), %xmm1 --- > movabsq $0, %rcx > cvtsi2ssq %rcx, %xmm1 81d76 < subss %xmm1, %xmm0 

cvtsi2ssq एक वास्तव में 10 गुना धीमा है

जाहिर है, float संस्करण मेमोरी से भरे हुए एक XMM रजिस्टर का उपयोग करता है, जबकि int संस्करण एक वास्तविक int मान 0 को cvtsi2ssq देता है, जो कि cvtsi2ssq निर्देश का उपयोग करके float करता है, बहुत समय लगता है। पासिंग- -O3 जीसीसी मदद नहीं करता है (जीसीसी संस्करण 4.2.1।)

( float बजाय double का उपयोग करना कोई फर्क नहीं पड़ता, सिवाय इसके कि यह cvtsi2ssq को एक cvtsi2sdq में cvtsi2sdq ।)

अद्यतन करें

कुछ अतिरिक्त परीक्षण दिखाते हैं कि यह जरूरी नहीं कि cvtsi2ssq निर्देश है। एक बार समाप्त (एक int ai=0;float a=ai; का उपयोग करके और 0 बजाय का उपयोग करके), गति अंतर बनी हुई है तो @ मिस्टिकियल सही है, denormalized फ्लोट फर्क पड़ता है इसे 0 और 0.1f बीच मानों का परीक्षण करके देखा जा सकता है उपरोक्त कोड में मोड़ लगभग 0.00000000000000000000000000000001 , जब छोरों को 10 बार लंबे समय तक ले जाता है।

अद्यतन << 1

इस दिलचस्प घटना का एक छोटा सा दृश्य:

  • स्तंभ 1: एक फ्लोट, प्रत्येक आवृत्ति के लिए 2 से विभाजित
  • कॉलम 2: इस फ्लोट के द्विआधारी प्रतिनिधित्व
  • कॉलम 3: इस फ्लोट को 1e7 गुणा करने के लिए लिया गया समय

आप स्पष्ट रूप से एक्सपोनेंट (अंतिम 9 बिट) को अपनी सबसे कम मूल्य में बदल सकते हैं, जब denormalization इनके अंदर सेट होता है। उस समय में, सरल परिवर्धन 20 गुना धीमा हो जाता है

 0.000000000000000000000000000000000100000004670110: 10111100001101110010000011100000 45 ms 0.000000000000000000000000000000000050000002335055: 10111100001101110010000101100000 43 ms 0.000000000000000000000000000000000025000001167528: 10111100001101110010000001100000 43 ms 0.000000000000000000000000000000000012500000583764: 10111100001101110010000110100000 42 ms 0.000000000000000000000000000000000006250000291882: 10111100001101110010000010100000 48 ms 0.000000000000000000000000000000000003125000145941: 10111100001101110010000100100000 43 ms 0.000000000000000000000000000000000001562500072970: 10111100001101110010000000100000 42 ms 0.000000000000000000000000000000000000781250036485: 10111100001101110010000111000000 42 ms 0.000000000000000000000000000000000000390625018243: 10111100001101110010000011000000 42 ms 0.000000000000000000000000000000000000195312509121: 10111100001101110010000101000000 43 ms 0.000000000000000000000000000000000000097656254561: 10111100001101110010000001000000 42 ms 0.000000000000000000000000000000000000048828127280: 10111100001101110010000110000000 44 ms 0.000000000000000000000000000000000000024414063640: 10111100001101110010000010000000 42 ms 0.000000000000000000000000000000000000012207031820: 10111100001101110010000100000000 42 ms 0.000000000000000000000000000000000000006103515209: 01111000011011100100001000000000 789 ms 0.000000000000000000000000000000000000003051757605: 11110000110111001000010000000000 788 ms 0.000000000000000000000000000000000000001525879503: 00010001101110010000100000000000 788 ms 0.000000000000000000000000000000000000000762939751: 00100011011100100001000000000000 795 ms 0.000000000000000000000000000000000000000381469876: 01000110111001000010000000000000 896 ms 0.000000000000000000000000000000000000000190734938: 10001101110010000100000000000000 813 ms 0.000000000000000000000000000000000000000095366768: 00011011100100001000000000000000 798 ms 0.000000000000000000000000000000000000000047683384: 00110111001000010000000000000000 791 ms 0.000000000000000000000000000000000000000023841692: 01101110010000100000000000000000 802 ms 0.000000000000000000000000000000000000000011920846: 11011100100001000000000000000000 809 ms 0.000000000000000000000000000000000000000005961124: 01111001000010000000000000000000 795 ms 0.000000000000000000000000000000000000000002980562: 11110010000100000000000000000000 835 ms 0.000000000000000000000000000000000000000001490982: 00010100001000000000000000000000 864 ms 0.000000000000000000000000000000000000000000745491: 00101000010000000000000000000000 915 ms 0.000000000000000000000000000000000000000000372745: 01010000100000000000000000000000 918 ms 0.000000000000000000000000000000000000000000186373: 10100001000000000000000000000000 881 ms 0.000000000000000000000000000000000000000000092486: 01000010000000000000000000000000 857 ms 0.000000000000000000000000000000000000000000046243: 10000100000000000000000000000000 861 ms 0.000000000000000000000000000000000000000000022421: 00001000000000000000000000000000 855 ms 0.000000000000000000000000000000000000000000011210: 00010000000000000000000000000000 887 ms 0.000000000000000000000000000000000000000000005605: 00100000000000000000000000000000 799 ms 0.000000000000000000000000000000000000000000002803: 01000000000000000000000000000000 828 ms 0.000000000000000000000000000000000000000000001401: 10000000000000000000000000000000 815 ms 0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 42 ms 0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 42 ms 0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 44 ms 

एआरएम के बारे में एक समान चर्चा स्टैक ओवरफ्लो प्रश्न में पाया जा सकता है- ऑर्डर सी-सी में डार्कलाइज्ड फ्लोटिंग पॉइंट?

यह denormalized फ़्लोटिंग-बिंदु उपयोग के कारण है यह दोनों और प्रदर्शन दंड से छुटकारा पाने के लिए कैसे? अभूतपूर्व संख्याओं को मारने के तरीकों के लिए इंटरनेट को दबाने के बाद ऐसा लगता है कि ऐसा करने के लिए अभी तक कोई "सर्वोत्तम" तरीका नहीं है। मुझे ये तीन तरीके मिले हैं जो विभिन्न वातावरणों में सर्वश्रेष्ठ काम कर सकते हैं:

  • कुछ जीसीसी वातावरण में काम नहीं कर सकते हैं:

     // Requires #include <fenv.h> fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV); 
  • कुछ दृश्य स्टूडियो परिवेशों में काम नहीं कर सकते हैं: 1

     // Requires #include <xmmintrin.h> _mm_setcsr( _mm_getcsr() | (1<<15) | (1<<6) ); // Does both FTZ and DAZ bits. You can also use just hex value 0x8040 to do both. // You might also want to use the underflow mask (1<<11) 
  • दोनों जीसीसी और विजुअल स्टूडियो में काम करने के लिए प्रकट होता है:

     // Requires #include <xmmintrin.h> // Requires #include <pmmintrin.h> _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); 
  • इंटेल कंपाइलर में आधुनिक इंटेल सीपीयू पर डिफॉर्मर को निष्क्रिय करने के विकल्प हैं I अधिक विवरण यहाँ

  • कंपाइलर स्विच -ffast-math , -msse या -mfpmath=sse को अक्षम कर देगा और कुछ अन्य चीजों को तेज कर देगा, लेकिन दुर्भाग्य से बहुत अधिक अन्य अनुमान भी -mfpmath=sse जो आपके कोड को तोड़ सकते हैं। सावधानी से परीक्षण करें! विज़ुअल स्टूडियो कंपाइलर के लिए फास्ट मैथ्यू के समतुल्य है /fp:fast लेकिन मैं यह पुष्टि करने में सक्षम नहीं हुआ है कि क्या यह भी denormals को अक्षम करता है। 1

जीसीसी में आप इस के साथ एफटीजेड और डीएजेज़ सक्षम कर सकते हैं:

 #include <xmmintrin.h> #define FTZ 1 #define DAZ 1 void enableFtzDaz() { int mxcsr = _mm_getcsr (); if (FTZ) { mxcsr |= (1<<15) | (1<<11); } if (DAZ) { mxcsr |= (1<<6); } _mm_setcsr (mxcsr); } 

जीसीसी स्विच का भी उपयोग करें: -msse -mfpmath = sse

(कार्ल हेथिंगटन के लिए संबंधित क्रेडिट [1])

[1] http://carlh.net/plugins/denormals.php