2012-02-19 30 views
7

मुझे एक __m128i चर के फ़ंक्शन की आवश्यकता है जिसमें अवधि 2^128 है। इसे एकान्त रूप से बढ़ने की आवश्यकता नहीं है (काउंटर की तरह), लेकिन एक बार प्रत्येक मान पर जाएं।128-बिट एसएसई काउंटर?

सबसे सरल उदाहरण मैं वास्तव में 128-बिट काउंटर के बारे में सोच सकता हूं, लेकिन मुझे एसएसई में लागू करना मुश्किल लगता है। क्या कोई आसान/तेज़ समाधान है?

+2

आपको 2^128 मूल्यों पर जाने की आवश्यकता क्यों है? पृथ्वी पर कोई कंप्यूटर ऐसा करने में सक्षम नहीं है। क्या आप 64-बिट int का उपयोग नहीं कर सकते? – usr

+0

सहमत हैं, गीगाहर्ट्ज के आदेश पर घड़ी की गति के साथ एक प्रोसेसर पर, आप 64-बिट काउंटर समाप्त होने से लगभग 584 साल के लिए प्रत्येक चक्र को एक नंबर का उपभोग कर सकते हैं। – Damon

उत्तर

5

यहां एक monotonic काउंटर है। मुझे यकीन नहीं है कि अगर आप इसे सरल कह सकते हैं।

मानते हैं कि ONE और ZERO दोनों पंजीयक में हैं, तो यह 5 निर्देशों को संकलित करना चाहिए। (7 या 8 यदि VEX एन्कोडिंग नहीं किया जाता है)

inline __m128i nextc(__m128i x){ 
    const __m128i ONE = _mm_setr_epi32(1,0,0,0); 
    const __m128i ZERO = _mm_setzero_si128(); 

    x = _mm_add_epi64(x,ONE); 
    __m128i t = _mm_cmpeq_epi64(x,ZERO); 
    t = _mm_and_si128(t,ONE); 
    t = _mm_unpacklo_epi64(ZERO,t); 
    x = _mm_add_epi64(x,t); 

    return x; 
} 

टेस्ट संहिता (MSVC):

int main() { 

    __m128i x = _mm_setr_epi32(0xfffffffa,0xffffffff,1,0); 

    int c = 0; 
    while (c++ < 10){ 
     cout << x.m128i_u64[0] << " " << x.m128i_u64[1] << endl; 
     x = nextc(x); 
    } 

    return 0; 
} 

आउटपुट:

18446744073709551610 1 
18446744073709551611 1 
18446744073709551612 1 
18446744073709551613 1 
18446744073709551614 1 
18446744073709551615 1 
0 2 
1 2 
2 2 
3 2 

थोड़ा बेहतर संस्करण ने सुझाव दिया @ नॉरबर्ट पी। यह मेरे मूल समाधान पर 1 निर्देश बचाता है।

inline __m128i nextc(__m128i x){ 
    const __m128i ONE = _mm_setr_epi32(1,0,0,0); 
    const __m128i ZERO = _mm_setzero_si128(); 

    x = _mm_add_epi64(x,ONE); 
    __m128i t = _mm_cmpeq_epi64(x,ZERO); 
    t = _mm_unpacklo_epi64(ZERO,t); 
    x = _mm_sub_epi64(x,t); 

    return x; 
} 
+0

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

+0

सवाल यह है कि, यदि यह किसी भी एसएसई का उपयोग न करने वाले समाधान से वास्तव में तेज़ है। मेरा मतलब है कि 2 64 बिट अनगिनत और 1 शाखा की संरचना का उपयोग करके स्पष्ट समाधान संभावित एसएसई ओवरहेड से बच जाएगा और शाखाएं बेहद अनुमानित होंगी। – Voo

+0

@Voo यह शायद इस बात पर निर्भर करेगा कि किस मूल्य में मूल्य की आवश्यकता है।यदि सामान्य रजिस्टरों या स्मृति में इसकी आवश्यकता है, तो 'एड + एडीसी' सबसे तेज़ होगा। यदि किसी एसएसई रजिस्टर में इसकी आवश्यकता है, तो 5 एसएसई-इंट निर्देश किसी भी प्रकार के निकालने/सम्मिलित होने की तुलना में तेज़ होंगे। एक स्ट्रक्चर/यूनियन के माध्यम से इसे स्मृति के माध्यम से पास करने से लोड/स्टोर बफर को रोक दिया जाएगा क्योंकि आप एक ही शब्द को एक अलग शब्द-आकार के साथ एक्सेस कर रहे हैं। – Mysticial

4

कभी भी KISS सिद्धांत को न भूलें।

चिपकाया जा रहा है इस (अहस्ताक्षरित पूर्णांकों सी मानक से चारों ओर लपेट के लिए है, इसलिए केवल एक बार प्रत्येक मूल्य का दौरा आवश्यक हैं): (64 के लिए)

__uint128_t inc(__uint128_t x) { 
    return x+1; 
} 

this में पैदावार:

addq $1, %rdi 
    adcq $0, %rsi 
    movq %rdi, %rax 
    movq %rsi, %rdx 
    ret 

आसान /काफी तेज़? आपको लगता है कि इनलाइन, तो आप शायद सिर्फ addq/adcq के साथ भाग प्राप्त करने में सक्षम हो जाएगा (movq और ret 64 ABI के लिए आवश्यक हैं: यदि आप समारोह इनलाइन, वे आवश्यक नहीं हैं)


MSVC की suckiness के बारे में Voo की टिप्पणी करने के लिए, आप निम्नलिखित का उपयोग कर सकते हैं: मैं एक MSVC पास के स्थापित तो मैं यह परीक्षण नहीं कर सकते नहीं है

inline void inc(unsigned long long *x, unsigned long long *y) { 
    if (!++*x) ++*y; // yay for obfuscation! 
} 

, लेकिन यह चाहिए उपज कुछ के समान मैंने ऊपर क्या पोस्ट किया। फिर, यदि आप वास्तव में को __m128i की आवश्यकता है, तो आप दो हिस्सों को cast करने में सक्षम होना चाहिए।

+0

इस समाधान के साथ समस्या यह है कि एसएसई रजिस्टरों में लोडिंग और भंडारण में काफी समय लगेगा। – jk4736

+0

उस कोड को मान्य है या नहीं, तो संकलक पर काफी निर्भर करता है। निश्चित रूप से यह एमएसवीसी के तहत नहीं है - __m128 केवल छोटे प्राइमेटिव्स के संघ की एक संरचना है। – Voo

+0

@ jk4736 मेरे स्निपेट में सभी रजिस्ट्रार गैर-एसएसई 64-बिट-चौड़े वाले हैं ... – CAFxX