दिलचस्प पोस्ट
PHP में डेटाबेस एक्सेस के साथ सिंगलटन के लिए उपयोग का कोई मामला है? मैं गतिशील बटन पर गतिशील बटन क्लिक ईवेंट कैसे बना सकता हूं? सी प्रोग्राम में वर्तमान निर्देशिका कैसे प्राप्त करें? AsyncTask का उपयोग कर एक से एक बार एक से अधिक फ़ाइलों को डाउनलोड करना है? MKPinAnnotationView: क्या तीन से अधिक रंग उपलब्ध हैं? गतिशील (संख्यात्मक) कुंजी नामों के साथ एक बच्चे ऑब्जेक्ट को कैसे डिसेरीलाइज़ करना? पायथन MySQLdb datetime.date और दशमलव को देता है मैं जावास्क्रिप्ट के साथ सीकेएडिट में एक मान कैसे सेट करूं? क्यू में वादों की एक चर संख्या को कैसे क्रमबद्ध करना है? JSONObject के अंदर कई JSONObjects के एंड्रॉइड जे एसओएन पार्सिंग सबसे तेज़ Matlab फाइल पढ़ने? दूरस्थ मशीन पर एक खोल स्क्रिप्ट को चलाने के लिए SSH का उपयोग कैसे करें? एक पेड़ बनाने के लिए स्वयं में घटक का प्रयोग करें सी + +: लाँगजम्प और सेटजेम्प का उपयोग करने के लिए सुरक्षित? अजगर: ज़िप की तरह काम है जो सबसे लंबे समय तक पैड है?

एक्स 86 पर क्षैतिज फ्लोट वेक्टर योग करने का सबसे तेज़ तरीका

आपके पास तीन (या चार) फ़्लोट्स के वेक्टर हैं उन्हें जमा करने का सबसे तेज़ तरीका क्या है?

एसएसई (movaps, फेरबदल, जोड़, movd) हमेशा x87 से अधिक तेज है? एसएसई 4.2 में क्षैतिज-जोड़ें निर्देश क्या हैं? एफपीयू में जाने की लागत क्या है, फिर एफडीपी, एफएपीपी? सबसे तेज विशिष्ट निर्देश अनुक्रम क्या है?

"चीजों को व्यवस्थित करने की कोशिश करें ताकि आप एक समय में चार वैक्टर जोड़ सकें" एक उत्तर के रूप में स्वीकार नहीं किया जाएगा। 🙂

Solutions Collecting From Web of "एक्स 86 पर क्षैतिज फ्लोट वेक्टर योग करने का सबसे तेज़ तरीका"

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

आम 2x hadd मुहावर केवल कोड-आकार के लिए अच्छा है, किसी भी मौजूदा CPU पर गति नहीं है इसमें उपयोग-मामले हैं (नीचे देखें), लेकिन यह उनमें से एक नहीं है।

मैंने एक AVX संस्करण भी शामिल किया है एवीएक्स / एवीएक्स 2 के साथ किसी भी प्रकार की क्षैतिज कमी को एक vextractf128 शुरू करना चाहिए और एक एक्सएमएम ( __m128 ) वेक्टर को कम करने के लिए एक "ऊर्ध्वाधर"

Godbolt Compiler Explorer पर इस सभी कोड से asm आउटपुट देखें। एगर फॉग के सी ++ वेक्टर क्लास लाइब्रेरी horizontal_add फ़ंक्शंस में भी मेरे सुधार देखें। ( संदेश बोर्ड धागा , और गिटूब पर कोड)। मैंने movdqa 2, एसएसई 4 और एवीएक्स के लिए कोड-साइज़ के लिए इष्टतम फेरबदल का चयन करने के लिए सीपीपी मैक्रोज़ का इस्तेमाल किया है, और जब AVX उपलब्ध नहीं है तो movdqa से बचने के लिए।


इस पर विचार करने के लिए सीमाएं हैं:

  • कोड का आकार: एल 1 आई-कैशे कारणों के लिए छोटा और बेहतर कोड (छोटे बाइनरी) से प्राप्त करने के लिए कुल बाइनरी आकार ज्यादातर एक कार्यक्रम में बार-बार किए गए संकलक निर्णयों के लिए महत्वपूर्ण होता है। यदि आप आंतरिक-कोड के साथ हाथ-कोड कुछ परेशान कर रहे हैं, तो यह कुछ कोड बाइट्स खर्च करने योग्य है, यदि वह पूरे कार्यक्रम के लिए किसी भी गति को बढ़ाता है (माइक्रोब्लैकमार्क की सावधान रहें, जो कि अच्छा प्रदर्शन न करें)।
  • ऊप-कैश आकार: अक्सर एल 1 I $ से अधिक कीमती 4 सिंगल-ऊप निर्देश 2 haddps तुलना में कम स्थान ले सकते हैं, इसलिए यह यहां अत्यधिक प्रासंगिक है।
  • विलंबता: कभी-कभी प्रासंगिक
  • थ्रूपुट: आम तौर पर अप्रासंगिक, क्षैतिज रकम आंतरिक लूप में नहीं होनी चाहिए।
  • कुल जुड़े हुए डोमेन यूप्स: यदि आसपास के कोड में उसी पोर्ट पर बाधा उत्पन्न नहीं होती जो एचएसयू उपयोग करता है, तो यह पूरी चीज के थ्रूपुट पर hsum के प्रभाव के लिए एक प्रॉक्सी है

जब क्षैतिज जोड़ कम होता है :

कोई यूओप-कैश के साथ सीपीयू 2x haddps पक्ष में हो सकता है: यह चलने पर धीमी haddps होता है, लेकिन यह अक्सर नहीं होता है केवल 2 निर्देश होने के कारण आसपास के कोड (आई $ आकार) पर प्रभाव कम करता है

यूओपी-कैश के साथ सीपीयू संभवत: कम कुछ लेता है जो कुछ कम हो जाता है, भले ही यह अधिक निर्देश / अधिक x 86 कोड-आकार हो। कुल यूप्स कैश-लाइन का इस्तेमाल किया गया है जिसे हम कम करना चाहते हैं, जो कुल यूप्स को कम करने के लिए उतना आसान नहीं है (शाखाएं और 32 बी की सीमाएं हमेशा एक नई ऊप कैश लाइन शुरू करते हैं)।

वैसे भी, उस ने कहा, क्षैतिज रकम बहुत ऊपर आती है, इसलिए मेरा ध्यान कुछ संस्करणों को क्राफ्टिंग करने का प्रयास है जो अच्छे तरीके से संकलित करते हैं। किसी भी वास्तविक हार्डवेयर पर बेंचमार्क नहीं, या यहां तक ​​कि ध्यान से परीक्षण फेरबदल स्थिरांक या कुछ में बग हो सकते हैं


यदि आप अपने कोड का फ़ॉलबैक / बेसलाइन संस्करण बना रहे हैं, तो याद रखें कि केवल पुराने CPU इसे चलाएंगे ; नए सीपीयू आपके एवीएक्स संस्करण, या एसएसई 4.1 या जो कुछ भी चलेंगे

पुरानी सीपीयू जैसे के 8, और कोर 2 (मेरॉम) और पहले ही 64 बिट फेफड़े इकाइयां हैं । कोर 2 में अधिकतम निर्देशों के लिए 128 बिट निष्पादन इकाइयां हैं, लेकिन शफ़ल के लिए नहीं। (पेंटियम एम और के 8 हेड 128 बी वेक्टर निर्देशों को दो 64 बिट हिस्सों के रूप में संभालते हैं)।

movhlps तरह movhlps जो 64 बिट के हिस्से में डेटा movhlps (64 बिट आधा के अंदर कोई फेरबदल नहीं) तेज भी हैं

धीमे शफ़ल के साथ पुराने CPU पर :

  • movhlps (Merom: 1uop) movhlps ( movhlps : 3 ओप्स) की तुलना में काफी तेज है। पेंटियम-एम पर, movaps से सस्ता। साथ ही, यह कोर 2 पर एफपी डोमेन में चलाता है, अन्य फेरबदल से बायपास विलंब से बचने के लिए
  • unpcklpd से भी तेज है।
  • pshufd धीमा है, pshuflw / pshufhw तेज है (क्योंकि वे केवल एक 64bit आधे घसीटना)
  • pshufb mm0 (MMX) तेज है, pshufb xmm0 धीमा है।
  • haddps बहुत धीमा है (मेरोम और पेंटियम एम पर 6 यूप्स)
  • movshdup (Merom: 1uop) दिलचस्प है : यह केवल 1uop insn है कि 64b तत्वों के भीतर shuffles है

shufps पर shufps (पेनिन सहित) आंकड़ों को पूर्णांक डोमेन में लाता है, जिससे addps लिए एफपी निष्पादन इकाइयों को वापस लाने के लिए बायपास विलंब addps , लेकिन movhlps पूरी तरह से एफपी डोमेन में होता है। shufpd भी फ्लोट डोमेन में चलाता है

movshdup पूर्णांक डोमेन में चलाता है, लेकिन केवल एक यूओपी है।

एएमडी के 10, इंटेल कोर 2 (पेनिन / वुल्फडेल), और बाद के सभी सीपीयू, एक एक्सएम के रूप में सभी एक्सएमएम फेरबदल को चलाएं। (लेकिन shufps पर shufps साथ बायपास विलंब ध्यान दें, shufps से बचा जाता है)


एवीएक्स के बिना, बर्बाद movaps / movdqa निर्देशों से बचने के लिए फेरबदल का सावधान विकल्प आवश्यक है । गंतव्य को संशोधित करने के बजाय, केवल कुछ शफ्ले एक कॉपी-और-फेर के रूप में काम करते हैं। दो आदानों (जैसे unpck* या movhlps ) से डेटा को जोड़ते हुए unpck* उपयोग एक movhlps चर के साथ किया जा सकता है जो अब _mm_movehl_ps(same,same) बजाय आवश्यक नहीं है _mm_movehl_ps(same,same)

इनमें से कुछ तेजी से (एक MOVAPS को बचा सकते हैं) बनाया जा सकता है, लेकिन प्रारंभिक फेरबदल के लिए गंतव्य के रूप में इस्तेमाल करने के लिए डमी एआरजी लेने के द्वारा यूगल / कम "क्लीन" उदाहरण के लिए:

 // Use dummy = a recently-dead variable that vec depends on, // so it doesn't introduce a false dependency, // and the compiler probably still has it in a register __m128d highhalf_pd(__m128d dummy, __m128d vec) { #ifdef __AVX__ // With 3-operand AVX instructions, don't create an extra dependency on something we don't need anymore. (void)dummy; return _mm_unpackhi_pd(vec, vec); #else // Without AVX, we can save a MOVAPS with MOVHLPS into a dead register __m128 tmp = _mm_castpd_ps(dummy); __m128d high = _mm_castps_pd(_mm_movehl_ps(tmp, _mm_castpd_ps(vec))); return high; #endif } 

एसएसई 1 (उर्फ एसएसई):

 float hsum_ps_sse1(__m128 v) { // v = [ DC | BA ] __m128 shuf = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 3, 0, 1)); // [ CD | AB ] __m128 sums = _mm_add_ps(v, shuf); // sums = [ D+C C+D | B+A A+B ] shuf = _mm_movehl_ps(shuf, sums); // [ CD | D+C C+D ] // let the compiler avoid a mov by reusing shuf sums = _mm_add_ss(sums, shuf); return _mm_cvtss_f32(sums); } # gcc 5.3 -O3: looks optimal movaps xmm1, xmm0 # I think one movaps is unavoidable, unless we have a 2nd register with known-safe floats in the upper 2 elements shufps xmm1, xmm0, 177 addps xmm0, xmm1 movhlps xmm1, xmm0 # note the reuse of shuf, avoiding a movaps addss xmm0, xmm1 # clang 3.7.1 -O3: movaps xmm1, xmm0 shufps xmm1, xmm1, 177 addps xmm1, xmm0 movaps xmm0, xmm1 shufpd xmm0, xmm0, 1 addss xmm0, xmm1 

मैंने शफ़ल्स को कम करने के बारे में एक झुंड बग की सूचना दी। इसकी फेरबदल के लिए इसका अपना आंतरिक प्रतिनिधित्व होता है, और वापस फेरबदल में बदल जाता है जीसीसी अधिक बार उन निर्देशों का उपयोग करता है जो आपके द्वारा प्रयोग किए गए आंतरिक से मेल खाते हैं।

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


SSE3

 float hsum_ps_sse3(__m128 v) { __m128 shuf = _mm_movehdup_ps(v); // broadcast elements 3,1 to 2,0 __m128 sums = _mm_add_ps(v, shuf); shuf = _mm_movehl_ps(shuf, sums); // high half -> low half sums = _mm_add_ss(sums, shuf); return _mm_cvtss_f32(sums); } # gcc 5.3 -O3: perfectly optimal code movshdup xmm1, xmm0 addps xmm0, xmm1 movhlps xmm1, xmm0 addss xmm0, xmm1 

इसमें कई फायदे हैं:

  • विनाशकारी फेरबदल (एवीएक्स के बिना) के आसपास काम करने के लिए किसी भी movaps प्रतियां की आवश्यकता नहीं है: movshdup xmm1, xmm2 का गंतव्य केवल लिखना है, इसलिए यह हमारे लिए मृत रजिस्टर के बाहर tmp बनाता है। यही कारण है कि मैंने movehl_ps(tmp, sums) बजाय movehl_ps(sums, sums) movehl_ps(tmp, sums) इस्तेमाल किया

  • छोटा कोड-आकार फेरबदल निर्देश छोटे हैं: movhlps 3 बाइट्स हैं, movshdup 4 बाइट्स ( shufps समान)। कोई तत्काल बाइट की आवश्यकता नहीं है, इसलिए AVX के साथ, vshufps 5 बाइट्स हैं, लेकिन vmovhlps और vmovshdup दोनों 4 हैं।

मैं addps बजाय addps साथ अन्य बाइट को बचा सकता हूं चूंकि यह आंतरिक छोरों के अंदर उपयोग नहीं किया जाएगा, अतिरिक्त ट्रांजिस्टर स्विच करने के लिए अतिरिक्त ऊर्जा संभवतः नगण्य है। ऊपरी 3 तत्वों से एफपी अपवाद एक जोखिम नहीं है, क्योंकि सभी तत्व मान्य एफपी डेटा रखते हैं। हालांकि, क्लैग / एलएलएमएम वास्तव में वेक्टर शफल्स को "समझता है", और बेहतर कोड का उत्सर्जन करता है यदि यह जानता है कि केवल निम्न तत्व के मामले हैं

SSE1 संस्करण की तरह, स्वयं को विषम तत्व जोड़कर एफपी अपवाद (जैसे अतिप्रवाह) हो सकता है जो अन्यथा नहीं होता, लेकिन यह समस्या नहीं होनी चाहिए। Denormals धीमी है, लेकिन IIRC एक + अध्याय के परिणाम उत्पादन सबसे uarches पर नहीं है


कोड-आकार के लिए एसएसई 3 अनुकूलन

यदि कोड-साइज आपकी प्रमुख चिंता है, तो दो haddps ( _mm_hadd_ps ) निर्देश चालें (पॉल आर का उत्तर) करेंगे। यह टाइप और याद रखने के लिए सबसे आसान भी है यह तेज नहीं है , हालांकि। यहां तक ​​कि इंटेल haddps अभी भी प्रत्येक haddps को 3 यूओप्स के लिए डीकोड करता है, जिसमें 6 चक्र विलंबता है। तो भले ही यह मशीन-कोड बाइट्स (एल 1 आई-कैश) बचाता है, यह अधिक मूल्यवान यूओपी-कैश में अधिक जगह लेता है। haddps लिए रियल उपयोग-केस: एक haddps atoi() कार्यान्वयन में एक मध्यवर्ती कदम पर एक संक्रमण और समस्या , या कुछ स्केलिंग करना ।


AVX:

यह संस्करण AVS प्रश्न के लिए एक कोड बाइट बनाम मारत के उत्तर को बचाता है।

 #ifdef __AVX__ float hsum256_ps_avx(__m256 v) { __m128 vlow = _mm256_castps256_ps128(v); __m128 vhigh = _mm256_extractf128_ps(v, 1); // high 128 vlow = _mm_add_ps(vlow, vhigh); // add the low 128 return hsum_ps_sse3(vlow); // and inline the sse3 version, which is optimal for AVX // (no wasted instructions, and all of them are the 4B minimum) } #endif vmovaps xmm1,xmm0 # huh, what the heck gcc? Just extract to xmm1 vextractf128 xmm0,ymm0,0x1 vaddps xmm0,xmm1,xmm0 vmovshdup xmm1,xmm0 vaddps xmm0,xmm1,xmm0 vmovhlps xmm1,xmm1,xmm0 vaddss xmm0,xmm0,xmm1 vzeroupper ret 

दोहरी सुनिश्चितता:

 double hsum_pd_sse2(__m128d vd) { // v = [ B | A ] __m128 undef = _mm_undefined_ps(); // don't worry, we only use addSD, never touching the garbage bits with an FP add __m128 shuftmp= _mm_movehl_ps(undef, _mm_castpd_ps(vd)); // there is no movhlpd __m128d shuf = _mm_castps_pd(shuftmp); return _mm_cvtsd_f64(_mm_add_sd(vd, shuf)); } # gcc 5.3.0 -O3 pxor xmm1, xmm1 # hopefully when inlined, gcc could pick a register it knew wouldn't cause a false dep problem, and avoid the zeroing movhlps xmm1, xmm0 addsd xmm0, xmm1 # clang 3.7.1 -O3 again doesn't use movhlps: xorpd xmm2, xmm2 # with #define _mm_undefined_ps _mm_setzero_ps movapd xmm1, xmm0 unpckhpd xmm1, xmm2 addsd xmm1, xmm0 movapd xmm0, xmm1 # another clang bug: wrong choice of operand order // This doesn't compile the way it's written double hsum_pd_scalar_sse2(__m128d vd) { double tmp; _mm_storeh_pd(&tmp, vd); // store the high half double lo = _mm_cvtsd_f64(vd); // cast the low half return lo+tmp; } # gcc 5.3 -O3 haddpd xmm0, xmm0 # Lower latency but less throughput than storing to memory # ICC13 movhpd QWORD PTR [-8+rsp], xmm0 # only needs the store port, not the shuffle unit addsd xmm0, QWORD PTR [-8+rsp] 

स्मृति को संग्रहीत करना और पीठ को एएलयू यूओप से बचा जाता है। यह अच्छा है कि अगर बंदरगाह का दबाव, या एएलयू सामान्य तौर पर बंद हो जाता है तो यह एक बाधा है। (ध्यान दें कि इसकी आवश्यकता नहीं है, sub rsp, 8 या कुछ भी क्योंकि एक्स 86-64 sub rsp, 8 एक लाल ज़ोन प्रदान करता है जो सिग्नल हैंडलर पर कदम नहीं sub rsp, 8 ।)

कुछ लोग एक सरणी में जमा करते हैं और सभी तत्वों को जमा करते हैं, लेकिन संकलक आमतौर पर यह नहीं समझते हैं कि सरणी के निम्न तत्व स्टोर से पहले एक रजिस्टर में मौजूद हैं।


पूर्णांक:

pshufd एक सुविधाजनक कॉपी और फेरबदल है बिट और बाइट पाली दुर्भाग्यवश जगह में हैं, और punpckhqdq परिणाम के निचले आधे हिस्से में गंतव्य के ऊंचे आधे हिस्से को movhlps हैं, जिस तरह से movhlps एक अलग रजिस्टर में हाई आधा निकाल सकते हैं।

पहले कदम के लिए movhlps का उपयोग कुछ सीपीयू पर अच्छा हो सकता है, लेकिन सिर्फ अगर हमारे पास खरोंच reg है pshufd एक सुरक्षित विकल्प है, और pshufd बाद सब कुछ पर तेज़ है

 int hsum_epi32_sse2(__m128i x) { #ifdef __AVX__ __m128i hi64 = _mm_unpackhi_epi64(x, x); // 3-operand non-destructive AVX lets us save a byte without needing a mov #else __m128i hi64 = _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2)); #endif __m128i sum64 = _mm_add_epi32(hi64, x); __m128i hi32 = _mm_shufflelo_epi16(sum64, _MM_SHUFFLE(1, 0, 3, 2)); // Swap the low two elements __m128i sum32 = _mm_add_epi32(sum64, hi32); return _mm_cvtsi128_si32(sum32); // SSE2 movd //return _mm_extract_epi32(hl, 0); // SSE4, even though it compiles to movd instead of a literal pextrd r32,xmm,0 } # gcc 5.3 -O3 pshufd xmm1,xmm0,0x4e paddd xmm0,xmm1 pshuflw xmm1,xmm0,0x4e paddd xmm0,xmm1 movd eax,xmm0 int hsum_epi32_ssse3_slow_smallcode(__m128i x){ x = _mm_hadd_epi32(x, x); x = _mm_hadd_epi32(x, x); return _mm_cvtsi128_si32(x); } 

कुछ सीपीयू पर, पूर्णांक डेटा पर एफपी शफल्स का उपयोग करना सुरक्षित है। मैंने यह ऐसा नहीं किया, क्योंकि आधुनिक CPUs पर जो कि 1 या 2 कोड बाइट्स को बचाएगा, बिना गति लाभ (कोड आकार / संरेखण प्रभावों के अलावा) के साथ।

SSE2

सभी चार:

 const __m128 t = _mm_add_ps(v, _mm_movehl_ps(v, v)); const __m128 sum = _mm_add_ss(t, _mm_shuffle_ps(t, t, 1)); 

R1 + R2 + R3:

 const __m128 t1 = _mm_movehl_ps(v, v); const __m128 t2 = _mm_add_ps(v, t1); const __m128 sum = _mm_add_ss(t1, _mm_shuffle_ps(t2, t2, 1)); 

मैंने पाया है कि इन्हें एक ही गति के रूप में डबल HADDPS (लेकिन मैंने बहुत बारीकी से मापा नहीं है) के रूप में देखा है।

आप इसे एसएसई 3 में दो HADDPS निर्देशों में कर सकते हैं:

 v = _mm_hadd_ps(v, v); v = _mm_hadd_ps(v, v); 

यह सभी तत्वों में राशि डालता है

मैं निश्चित रूप से एसएसई 4.2 को एक कोशिश देगा। यदि आप यह कई बार कर रहे हैं (मुझे लगता है कि आप हैं यदि प्रदर्शन एक मुद्दा है), आप (1, 1,1,1) के साथ एक रजिस्टर को पूर्व-लोड कर सकते हैं, और उसके बाद कई डॉट 4 (my_vec (s), one_vec) कर सकते हैं इस पर। हां, यह एक अति आवश्यक गुणा है, लेकिन ये इन दिनों काफी सस्ता हैं और इस तरह के ऑप्शन पर क्षैतिज निर्भरताओं का वर्चस्व होने की संभावना है, जो नए एसएसई डॉट उत्पाद समारोह में अधिक अनुकूलित हो सकता है। आपको यह देखने के लिए परीक्षण करना चाहिए कि क्या यह दोहरी क्षैतिज को पीछे छोड़ देता है

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