SIMD minmag and maxmag

前端 未结 1 1908
太阳男子
太阳男子 2021-01-12 09:33

I want to implement SIMD minmag and maxmag functions. As far as I understand these functions are

minmag(a,b) = |a|<|b| ? a : b
maxmag(a,b) = |a|>|b| ?         


        
1条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-12 10:05

    Here's an alternate implementation which uses fewer instructions:

    static inline void maxminmag_test(__m128d & a, __m128d & b) {
        __m128d cmp     = _mm_add_pd(a, b); // test for mean(a, b) >= 0
        __m128d amin    = _mm_min_pd(a, b);
        __m128d amax    = _mm_max_pd(a, b);
        __m128d minmag  = _mm_blendv_pd(amin, amax, cmp);
        __m128d maxmag  = _mm_blendv_pd(amax, amin, cmp);
        a = maxmag, b = minmag;
    }
    

    It uses a somewhat subtle algorithm (see below), combined with the fact that we can use the sign bit as a selection mask.

    It also uses @EOF's suggestion of using only one mask and switching the operand order, which saves an instruction.

    I've tested it with a small number of cases and it seems to match your original implementation.


    Algorithm:

     if (mean(a, b) >= 0)       // this can just be reduced to (a + b) >= 0
     {
         minmag = min(a, b);
         maxmag = max(a, b);
     }
     else
     {
         minmag = max(a, b);
         maxmag = min(a, b);
     }
    

    0 讨论(0)
提交回复
热议问题