كومباكت أفكس 2 سجل حتى الأعداد الصحيحة المحددة هي متجاورة وفقا لقناع [مكررة]

StackOverflow https://stackoverflow.com//questions/25074197

  •  26-12-2019
  •  | 
  •  

سؤال

في السؤال تحسين ضغط الصفيف, ، تنص الإجابة العليا على:

سس / أفكس سجلات مع أحدث مجموعات التعليمات تسمح نهج أفضل.يمكننا استخدام نتيجة بموفمسكب مباشرة ، وتحويله إلى سجل التحكم لشيء مثل بشوفب.

هل هذا ممكن مع هاسويل (أفكس 2)?أم أنها تتطلب واحدة من نكهات أفكس 512?

لقد حصلت على ناقلات أفكس 2 تحتوي على إنت32 ثانية ، وناقل المقابلة من نتيجة مقارنة.أريد أن خلط بطريقة أو بأخرى بحيث العناصر مع مسب المقابلة مجموعة في قناع (قارن صحيح) متجاورة في نهاية منخفضة من ناقلات.

أفضل ما يمكنني رؤيته هو الحصول على قناع قليلا مع _ مم 256_ موفيماسكبس / فموفمسكبس (لا * د البديل?) ثم استخدم ذلك في جدول بحث متجه 256 أفكس 2 للحصول على قناع خلط عشوائي للممر المتقاطع _ مم 256 _ بيرموتيفار 8 إكس 32 _ إيبي 32/فبرمد

هل كانت مفيدة؟

المحلول

أول شيء يجب فعله هو العثور على وظيفة عددية سريعة.هنا هو الإصدار الذي لا يستخدم فرع.

inline int compact(int *x, int *y, const int n) {
    int cnt = 0;
    for(int i=0; i<n; i++) {
        int cut = x[i]!=0;
        y[cnt] = cut*x[i];
        cnt += cut;
    }
    return cnt;
}

أفضل نتيجة مع سيمد ربما يعتمد على توزيع الأصفار.إذا كان متناثرا أو كثيفا .يجب أن يعمل الكود التالي بشكل جيد للتوزيع المتناثر أو الكثيف.على سبيل المثال المسافات الطويلة من الأصفار وغير الأصفار.إذا كان التوزيع أكثر حتى لا أعرف ما إذا كان هذا الرمز سيكون له أي فائدة.لكنها ستعطي النتيجة الصحيحة على أي حال.

هنا هو نسخة أفكس 2 اختبرت.

int compact_AVX2(int *x, int *y, int n) {
    int i =0, cnt = 0;
    for(i=0; i<n-8; i+=8) {
        __m256i x4 = _mm256_loadu_si256((__m256i*)&x[i]);
        __m256i cmp = _mm256_cmpeq_epi32(x4, _mm256_setzero_si256());
        int mask = _mm256_movemask_epi8(cmp);
        if(mask == -1) continue; //all zeros
        if(mask) {
            cnt += compact(&x[i],&y[cnt], 8);
        }
        else {
            _mm256_storeu_si256((__m256i*)&y[cnt], x4);
            cnt +=8;
        }       
    }
    cnt += compact(&x[i], &y[cnt], n-i); // cleanup for n not a multiple of 8
    return cnt;
}

هنا هو الإصدار سس 2 اختبرت.

int compact_SSE2(int *x, int *y, int n) {
    int i =0, cnt = 0;
    for(i=0; i<n-4; i+=4) {
        __m128i x4 = _mm_loadu_si128((__m128i*)&x[i]);
        __m128i cmp = _mm_cmpeq_epi32(x4, _mm_setzero_si128());
        int mask = _mm_movemask_epi8(cmp);
        if(mask == 0xffff) continue; //all zeroes
        if(mask) {
            cnt += compact(&x[i],&y[cnt], 4);
        }
        else {
            _mm_storeu_si128((__m128i*)&y[cnt], x4);
            cnt +=4;
        }       
    }
    cnt += compact(&x[i], &y[cnt], n-i); // cleanup for n not a multiple of 4
    return cnt;
}

هنا هو اختبار كامل

#include <stdio.h>
#include <stdlib.h>
#if defined (__GNUC__) && ! defined (__INTEL_COMPILER)
#include <x86intrin.h>                
#else
#include <immintrin.h>                
#endif

#define N 50

inline int compact(int *x, int *y, const int n) {
    int cnt = 0;
    for(int i=0; i<n; i++) {
        int cut = x[i]!=0;
        y[cnt] = cut*x[i];
        cnt += cut;
    }
    return cnt;
}

int compact_SSE2(int *x, int *y, int n) {
        int i =0, cnt = 0;
        for(i=0; i<n-4; i+=4) {
            __m128i x4 = _mm_loadu_si128((__m128i*)&x[i]);
            __m128i cmp = _mm_cmpeq_epi32(x4, _mm_setzero_si128());
            int mask = _mm_movemask_epi8(cmp);
            if(mask == 0xffff) continue; //all zeroes
            if(mask) {
                cnt += compact(&x[i],&y[cnt], 4);
            }
            else {
                _mm_storeu_si128((__m128i*)&y[cnt], x4);
                cnt +=4;
            }       
        }
        cnt += compact(&x[i], &y[cnt], n-i); // cleanup for n not a multiple of 4
        return cnt;
    }

int compact_AVX2(int *x, int *y, int n) {
    int i =0, cnt = 0;
    for(i=0; i<n-8; i+=8) {
        __m256i x4 = _mm256_loadu_si256((__m256i*)&x[i]);
        __m256i cmp = _mm256_cmpeq_epi32(x4, _mm256_setzero_si256());
        int mask = _mm256_movemask_epi8(cmp);
        if(mask == -1) continue; //all zeros
        if(mask) {
            cnt += compact(&x[i],&y[cnt], 8);
        }
        else {
            _mm256_storeu_si256((__m256i*)&y[cnt], x4);
            cnt +=8;
        }       
    }
    cnt += compact(&x[i], &y[cnt], n-i); // cleanup for n not a multiple of 8
    return cnt;
}

int main() {
    int x[N], y[N];
    for(int i=0; i<N; i++) x[i] = rand()%10;
    //int cnt = compact_SSE2(x,y,N);
    int cnt = compact_AVX2(x,y,N);
    for(int i=0; i<N; i++) printf("%d ", x[i]); printf("\n");
    for(int i=0; i<cnt; i++) printf("%d ", y[i]); printf("\n");
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top