2016-12-01 6 views
5

का उपयोग कर किसी चरित्र का पहला उदाहरण ढूंढें, मैं इस मामले में सिमड (AVX2 या इससे पहले) का उपयोग करते हुए किसी चरित्र के पहले उदाहरण को खोजने का प्रयास कर रहा हूं। मैं _mm256_cmpeq_epi8 का उपयोग करना चाहता हूं, लेकिन फिर मुझे आवश्यकता है __m256i में परिणामी बाइट्स में से कोई भी 0xFF पर सेट किया गया है, तो यह खोजने का एक त्वरित तरीका है। इस योजना को बाइट्स से बिट्स में परिणाम बदलने के लिए _mm256_movemask_epi8 का उपयोग करने के लिए, और मिलान सूचकांक प्राप्त करने के लिए ffs का उपयोग करने के लिए किया गया था। क्या यह बेहतर है बाहरसिमड

+0

मुझे जोड़ना चाहिए, सिमड आवश्यक नहीं है, आम तौर पर मैं बस सबसे तेज़ दृष्टिकोण की तलाश में हूं। शायद थोड़ा सा जादू? – Jimbo

+1

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

+1

[यहां एक एसएसई कार्यान्वयन है जो '' 0 0''] (http://stackoverflow.com/a/14524319/253056) (प्रभावी रूप से 'strlen') के लिए स्ट्रिंग स्कैन करता है, जिसे आप अनुकूलित करने में सक्षम हो सकते हैं। –

उत्तर

4

_mm_movemask_epi8 का उपयोग कर एक समय में एक हिस्से को स्थानांतरित करने के लिए किसी भी अन्य सुझावों आप _mm256_cmpeq_epi8 के साथ सही विचार है? -।।>_mm256_movemask_epi8 AFAIK, कि इंटेल CPU के लिए इस लागू करने के लिए इष्टतम तरीका है कम से कम PMOVMSKB r32, ymm एक ही गति है एक्सएमएम 16-बाइट संस्करण के रूप में, इसलिए यह दो एल को अनपैक करने के लिए एक बड़ा नुकसान होगा 256 बी वेक्टर की एनीज और उन्हें अलग-अलग ले जाएं और फिर पूर्णांक परिणामों को पुन: संयोजित करें। (स्रोत:। Agner Fog's instruction table टैग विकि में अन्य पर्फ़ लिंक देखें।)

जब तक आप _mm256_movemask_epi8 से एक गैर शून्य परिणाम की पहचान की है ffs छोड़ कर संभव के रूप में कुशल के रूप में पाश अंदर कोड बनाओ।

टेस्ट/जेसीसी एक ही यूओपी में मैक्रो फ्यूज कर सकता है, लेकिन बीएसएफ/जेसीसी नहीं करता है, इसलिए यह एक अतिरिक्त निर्देश लेता है। (और आपको बीएसएफ/जेसीसी को छोड़ने के लिए सी संकलक प्राप्त करने के लिए कड़ी मेहनत की जाएगी। ffs के परिणामस्वरूप शाखाओं की संभावना आपको शून्य के इनपुट के लिए किसी प्रकार का परीक्षण देगी, फिर बीएसएफ, फिर 1 जोड़ें , फिर तुलना-और-शाखा। यह केवल हलचल परिणाम का परीक्षण करने की तुलना में भयानक है।)

यह भी ध्यान दें कि इसी तरह की समस्याओं के लिए, movemask की तुलना करना (उदाहरण के लिए यह जांचें कि यह 0xFFFFFFFF है) इस पर शाखा बनाने के समान ही कुशल है शून्य होने के नाते।


पॉल आर के रूप में सुझाव दिया, कुछ strlen, strchr को देखते हुए, और memchr कार्यान्वयन जानकारीपूर्ण हो सकता है। ओपन-सोर्स libc कार्यान्वयन, और अन्य स्थानों में कई हाथ से लिखित एएसएम कार्यान्वयन हैं। (जैसे glibc, और Agner Fog's asmlib।)

glibc के संस्करणों में से कई एक संरेखण सीमा से ऊपर स्कैन, फिर, एक unrolled पाश है कि (एक समय में 64B पढ़ता 4 SSE वैक्टर में उपयोग के बाद से मुझे नहीं लगता कि glibc एक AVX2 है है संस्करण)।

लंबे तारों के लिए अनुकूलित करने के लिए, तुलना परिणामों को परीक्षण करके ओवरहेड को कम करके परिणामों की तुलना करके, और जांचें। यदि आपको हिट मिलती है, तो वापस जाएं और अपने वेक्टरों को दोबारा जांचें ताकि वेक्टर को हिट किया जा सके।

यह एक 64-बिट पूर्णांक पर ffs करने के लिए कुछ और अधिक कुशल हो सकता है जिसे आपने एकाधिक मूवमास्क परिणामों से बनाया है (शिफ्ट और | के साथ)। मुझे शून्य के परीक्षण से पहले लूप के अंदर ऐसा करने के बारे में निश्चित नहीं है; मुझे याद नहीं है कि ग्लिब की स्ट्रेल रणनीतियों में से एक ने ऐसा किया या नहीं।


सब कुछ मैं यहाँ का सुझाव दिया है सामान strlen, memchr, और संबंधित कार्यों के लिए विभिन्न glibc रणनीतियों में एएसएम में देखा जा सकता है। यहां sysdeps/x86_64/strlen.S है, लेकिन मैं बेसलाइन एसएसई 2 से कहीं अधिक उपयोग कर कहीं और स्रोत फ़ाइल हो सकता हूं। । (या नहीं, मुझे कोई दूसरी समारोह का, सोच रहे होंगे कि शायद कुछ भी नहीं SSE2 परे प्राप्त होने, AVX (3-संकार्य insns) और AVX2 तक (256b पूर्णांक वैक्टर) वहाँ

यह भी देखें:

  • glibc का strchr-avx2.S (Woboq.org के पास फ़ाइल नाम/प्रतीकों के लिए उपयोगी खोज के साथ एक अच्छा स्रोत ब्राउज़र है)।
  • glibc के memchr-avx2.S

glibc's memchr POR के बजाय PMAXUB उपयोग करता है। मुझे यकीन नहीं है कि यह कुछ आर्केन माइक्रोआर्किटेक्चरल कारणों के लिए उपयोगी है, लेकिन यह अधिकांश CPUs पर कम बंदरगाहों पर चलता है। शायद वांछित है, किसी और के साथ संसाधन संघर्ष से बचने के लिए? आईडीके, अजीब लगता है, क्योंकि यह पीसीएमपीईक्यूबी के साथ प्रतिस्पर्धा करता है।

+0

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

+0

@ जिम्बो: ओह हम्म, मैंने नोटिस नहीं किया था कि स्केलेक के लिए एग्नेर फोग की तालिका में पीएमओवीएमएसकेबी आर, वी' 2-3 सी विलंबता के रूप में सूचीबद्ध है। हैसवेल पर, 'वीएमओवीएमएसकेपीएस/डी आर 32, वाईएमएम 2 सी विलंबता है, लेकिन एक्सएम संस्करण 3 सी विलंबता है! यह आश्चर्यजनक है। आप कहां देख रहे हैं कि 256 बी संस्करण धीमा है? क्या आप सुनिश्चित हैं कि स्केलेक पर ymm संस्करण तेज नहीं है? –

+0

@ जिम्बो: वैसे भी, अंतर विलंबता के अधिकांश चक्र और कोई अतिरिक्त यूओपीएस या थ्रूपुट पर नहीं है। ** '_mm256_movemask_epi8' अभी भी सबसे अच्छा है जो आप कर सकते हैं **। आप दो हिस्सों के साथ अलग-अलग कुछ भी नहीं कर सकते हैं, संभवतः एक वीपीएमओवीएमएसकेबी आर 32, वाईएमएम के उपयोग के रूप में उतना ही अच्छा हो सकता है। ऊपरी लेन पर एक 128 बी movmsk का उपयोग करने के लिए इसे पहले पंजीकरण के कम 128b तक निकालने की आवश्यकता होगी, जिसमें 3-चक्र विलंबता लेन-क्रॉसिंग शफल जैसे VEXTRACTF128। –

संबंधित मुद्दे