दिलचस्प पोस्ट
एंड्रॉइड स्टूडियो: यूटिफ़ -8 एन्कोडिंग के लिए अनुपयोगी चरित्र एनिमेटेड जीआईएफ़ प्रदर्शित करें मुख्य थ्रेड पर एक लंबे समय से चलने वाले पार्स ऑपरेशन को निष्पादित किया जा रहा है JSP उदाहरण के साथ एक सरल AJAX Django: कैसे एक कस्टम प्रपत्र विजेट बनाने के लिए? एडीबी डिवाइस नाम से एंड्रॉइड एवीडी नाम कैसे प्राप्त करें एकाधिक फ़ाइलों में पायथन ग्लोबल वेरिएबल मॉनिटर का सही भौतिक आकार कैसे प्राप्त करें? Gradle संस्करण 1.10 की आवश्यकता है। वर्तमान संस्करण 2.0 है एंड्रॉइड स्टूडियो के साथ अहस्ताक्षरित एपीके फ़ाइल बनाएं जावा में सूची में सरणी परिवर्तित करना डेटाफ्रेम समूह व्यवहार / ऑप्टिमाइज़ेशन से मैं कुछ ऐसा कैसे कर सकता हूं जो WinForms एप्लिकेशन में सभी 'अनियंत्रित' अपवादों को पकड़ता है? इनलाइन-फ़ॉर्म के अंदर पूर्ण-चौड़ाई टेक्स्ट-इनपुट बूटस्ट्रैप करें PHP के लिए FOREACH में प्रदर्शन

X86 पर फ्लोट को इंट में बदलने का सबसे तेज़ तरीका क्या है

एक एक्स 86 सीपीयू पर फ़्लोटिंग-पॉइंट नंबर को एक इंट में कनवर्ट करने का सबसे तेज़ तरीका क्या है पूर्व में सी या असेंबली में (जो कि सी में तैयार किया जा सकता है) निम्न में से किसी भी संयोजन के लिए:

  • 32/64/80-बिट फ्लोट -> 32/64-बिट पूर्णांक

मैं कुछ तकनीक की तलाश कर रहा हूं जो कि संकलक द्वारा ऐसा करने के बजाय तेज़ है।

Solutions Collecting From Web of "X86 पर फ्लोट को इंट में बदलने का सबसे तेज़ तरीका क्या है"

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

http://www.stereopsis.com/FPU.html

एसएसई का उपयोग करके पैक्ड रूपांतरण का सबसे तेज़ तरीका है, क्योंकि आप एक ही अनुदेश में एक से अधिक मान बदल सकते हैं। ffmpeg इस के लिए बहुत सी विधानसभाएं हैं (ज्यादातर ऑडियो के डीकोड आउटपुट को पूर्णांक नमूने में बदलने के लिए); कुछ उदाहरणों के लिए इसे जांचें

सादे x86 / x87 कोड के लिए आमतौर पर इस्तेमाल की जाने वाली चाल, फ्लोट के मंटिसा भाग को इंट का प्रतिनिधित्व करने के लिए बाध्य करना है। 32 बिट संस्करण निम्नानुसार है।

64-बिट संस्करण अनुरूप है ऊपर लिवा संस्करण लिवा तेज है, लेकिन एक 32-बिट परिणाम के लिए डबल के कटौती पर निर्भर करता है, इसलिए इसके लिए एक्स 7 यूनिट की आवश्यकता होती है जिसे डबल सटीक सेट किया जा सकता है, और इसे डबल से 64-बिट इंट रूपांतरण के लिए अनुकूलित नहीं किया जा सकता है।

इस कोड के बारे में अच्छी बात यह है कि यह आईईईई 754 के अनुरूप सभी प्लेटफॉर्मों के लिए पूरी तरह से पोर्टेबल है, एकमात्र धारणा है कि फ्लोटिंग पॉइंट गोलिंग मोड निकटतम पर सेट है नोट: अर्थ में पोर्टेबल यह संकलन और काम करता है X86 के अलावा अन्य प्लेटफॉर्म आमतौर पर इस तकनीक से बहुत फायदा नहीं लेते हैं, यदि बिल्कुल।

static const float Snapper=3<<22; union UFloatInt { int i; float f; }; /** by Vlad Kaipetsky portable assuming FP24 set to nearest rounding mode efficient on x86 platform */ inline int toInt( float fval ) { Assert( fabs(fval)<=0x003fffff ); // only 23 bit values handled UFloatInt &fi = *(UFloatInt *)&fval; fi.f += Snapper; return ( (fi.i)&0x007fffff ) - 0x00400000; } 

विधानसभा में एक अंतर में एक फ्लोटिंग बिंदु को परिवर्तित करने के लिए एक निर्देश है: FISTP निर्देश का उपयोग करें यह फ्लोटिंग-पॉइंट स्टैक से मूल्य पॉप करता है, इसे पूर्णांक में परिवर्तित करता है, और फिर निर्दिष्ट पते पर स्टोर करता है मुझे नहीं लगता कि वहाँ एक तेज़ तरीका होगा (जब तक आप एमएमएक्स या एसएसई जैसे विस्तारित निर्देशों का उपयोग नहीं करते हैं, जिसे मैं परिचित नहीं हूं)।

एक अन्य निर्देश, FIST, एफपी स्टैक पर मूल्य छोड़ देता है लेकिन मुझे यकीन नहीं है कि यह क्वैड-शब्द आकार के गंतव्यों के साथ काम करता है।

यदि आप गारंटी दे सकते हैं कि आपका कोड चलाने वाला सीपीयू SSE3 संगत है (यहां तक ​​कि Pentium 5 है, जेबीबी), तो आप कंपाइलर को अपने फास्टटीपी निर्देश का उपयोग करने की अनुमति दे सकते हैं (अर्थात जीएससी के लिए एमएमएस 3)। ऐसा लगता है कि ऐसा करना हमेशा करना चाहिए था:

http://software.intel.com/en-us/articles/how-to-implement-the-fisttp-streaming-simd-extensions-3-instruction/

ध्यान दें कि FISTTP, FISTP से अलग है (इसकी समस्याएं हैं, धीमे होने के कारण)। यह एसएसई 3 के भाग के रूप में आता है लेकिन वास्तव में (केवल) X87-side शोधन

अन्य तो एक्स 86 सीपीयू शायद रूपांतरण ठीक कर देगा, वैसे भी। 🙂

SSE3 समर्थन के साथ प्रोसेसर

लिआ कोड बेस में ऐसा करने के लिए निम्नलिखित स्निपेट हैं (www.lua.org से src / luaconf.h में जांच करें)। यदि आप (एसए निकलते हैं) एक तेज रास्ता मिल जाए, तो मुझे यकीन है कि वे रोमांचित होंगे।

ओह, lua_Number मतलब दोहरी है 🙂

 /* @@ lua_number2int is a macro to convert lua_Number to int. @@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ** CHANGE them if you know a faster way to convert a lua_Number to ** int (with any rounding method and without throwing errors) in your ** system. In Pentium machines, a naive typecast from double to int ** in C is extremely slow, so any alternative is worth trying. */ /* On a Pentium, resort to a trick */ #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) /* On a Microsoft compiler, use assembler */ #if defined(_MSC_VER) #define lua_number2int(i,d) __asm fld d __asm fistp i #define lua_number2integer(i,n) lua_number2int(i, n) /* the next trick should work on any Pentium, but sometimes clashes with a DirectX idiosyncrasy */ #else union luai_Cast { double l_d; long l_l; }; #define lua_number2int(i,d) \ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } #define lua_number2integer(i,n) lua_number2int(i, n) #endif /* this option always works, but may be slow */ #else #define lua_number2int(i,d) ((i)=(int)(d)) #define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) #endif 

यदि आप वास्तव में इस की गति के बारे में ध्यान रखते हैं तो सुनिश्चित करें कि आपका कंपाइलर FIST निर्देश जनरेट कर रहा है। एमएसवीसी में आप / QIfist के साथ ऐसा कर सकते हैं, यह एमएसडीएन अवलोकन देखें

आप अपने लिए काम करने के लिए एसएसई इंट्रिंसिक्स का इस्तेमाल कर सकते हैं, इंटेल से यह लेख देखें: http://softwarecommunity.intel.com/articles/eng/2076.htm

चूंकि एमएस हमें एक्स 64 में इनलाइन असेंबली से बाहर निकाल लेता है और हमें इंट्रिंसिक्स का उपयोग करने के लिए मजबूर करता है, इसलिए मैंने देखा कि किसका उपयोग करना है। MSDN दस्तावेज़ एक उदाहरण के साथ _mm_cvtsd_si64x देता है

उदाहरण काम करता है, लेकिन बेहद अक्षम है, 2 युगल के अनलिखित लोड का उपयोग करते हुए, जहां हमें एक सिंगल लोड की आवश्यकता होती है, इसलिए अतिरिक्त संरेखण आवश्यकता से छुटकारा मिल रहा है। फिर बहुत सारे अनावश्यक बोझ और पुनः लोड किए जाते हैं, लेकिन इन्हें हटाया जा सकता है:

  #include <intrin.h> #pragma intrinsic(_mm_cvtsd_si64x) long long _inline double2int(const double &d) { return _mm_cvtsd_si64x(*(__m128d*)&d); } 

परिणाम:

  i=double2int(d); 000000013F651085 cvtsd2si rax,mmword ptr [rsp+38h] 000000013F65108C mov qword ptr [rsp+28h],rax 

गोल मोड को इनलाइन असेंबली के बिना सेट किया जा सकता है, उदा

  _control87(_RC_NEAR,_MCW_RC); 

जहां नज़दीकी से घूमना डिफ़ॉल्ट है (वैसे भी)।

सवाल है कि प्रत्येक कॉल में गोलाई मोड सेट करना है या इसे ग्रहण करने के लिए बहाल किया जाएगा (तृतीय पक्ष लिब्स) का अनुभव के आधार पर जवाब देना होगा, मुझे लगता है आपको float.h _control87() और संबंधित स्थिरांक के लिए float.h को शामिल करना होगा।

और, नहीं, यह 32 बिट में काम नहीं करेगा, इसलिए FISTP निर्देश का उपयोग करते रहें:

 _asm fld d _asm fistp i 

मुझे लगता है कि तुल्यता की आवश्यकता है, जैसे कि कोई लिखता है i = (int)f "c" में

यदि आपके पास SSE3 है, तो आप इसका उपयोग कर सकते हैं:

 int convert(float x) { int n; __asm { fld x fisttp n // the extra 't' means truncate } return n; } 

वैकल्पिक रूप से, SSE2 के साथ (या x64 में जहां इनलाइन असेंबली उपलब्ध नहीं हो), आप लगभग उपवास के रूप में उपयोग कर सकते हैं:

 #include <xmmintrin.h> int convert(float x) { return _mm_cvtt_ss2si(_mm_load_ss(&x)); // extra 't' means truncate } 

पुराने कंप्यूटर्स पर गोल मोड को मैन्युअल रूप से सेट करने और साधारण fistp निर्देश का उपयोग करने के लिए रूपांतरण का विकल्प होता है। यह शायद केवल तैर के सरणियों के लिए काम करेगा, अन्यथा किसी भी निर्माण का उपयोग न करने के लिए सावधानी से किया जाना चाहिए जो कम्पाइलर को गोलाकार मोड (जैसे ढलाई) के रूप में परिवर्तित कर देगा। ऐसा किया जाता है:

 void Set_Trunc() { // cw is a 16-bit register [_ _ _ ic rc1 rc0 pc1 pc0 iem _ pm um om zm dm im] __asm { push ax // use stack to store the control word fnstcw word ptr [esp] fwait // needed to make sure the control word is there mov ax, word ptr [esp] // or pop ax ... or ax, 0xc00 // set both rc bits (alternately "or ah, 0xc") mov word ptr [esp], ax // ... and push ax fldcw word ptr [esp] pop ax } } void convertArray(int *dest, const float *src, int n) { Set_Trunc(); __asm { mov eax, src mov edx, dest mov ecx, n // load loop variables cmp ecx, 0 je bottom // handle zero-length arrays top: fld dword ptr [eax] fistp dword ptr [edx] loop top // decrement ecx, jump to top bottom: } } 

ध्यान दें कि इनलाइन असेंबली केवल माइक्रोसॉफ्ट के विजुअल स्टूडियो कंपाइलर्स (और शायद बोर्लैंड) के साथ काम करती है, जीसीसी के संकलन के लिए इसे जीएनयू असेंबली में फिर से लिखना होगा। आत्मनिष्ठता के साथ एसएसई 2 समाधान काफी पोर्टेबल होना चाहिए, हालांकि।

अन्य गोलाकार मोड विभिन्न एसएसई 2 इंट्रिंसिक्स द्वारा या मैन्युअल रूप से एफपीयू कंट्रोल शब्द को एक अलग गोलाई मोड में सेट करके संभव है।

आम तौर पर, आप कम्पाइलर को कुशल और सही होने पर भरोसा कर सकते हैं। आमतौर पर कंपाइलर में मौजूद कुछ चीज़ों के लिए अपने स्वयं का फ़ंक्शन रोल करके प्राप्त करने के लिए कुछ भी नहीं है