2015-10-22 24 views
2

假設我有兩個新值和新值。 我想實現向量化函數 ,如果abs(x-y)< p返回舊的,否則返回新的。simd代碼來檢查兩個double值是否足夠不同

下面是代碼(TEST.CPP):

#include <emmintrin.h> 
#include <iostream> 

#define ARRAY_LENGTH 2 

int main(void) { 
    // x = old value, y = new value, res = result 
    double *x, *y, *res; 
    posix_memalign((void **)&x, 16, sizeof(double) * ARRAY_LENGTH); 
    posix_memalign((void **)&y, 16, sizeof(double) * ARRAY_LENGTH); 
    posix_memalign((void **)&res, 16, sizeof(double) * ARRAY_LENGTH); 

    double p = 1e-4; // precision 
    __m128d sp = _mm_set1_pd(p); 
    x[0] = 1.5; y[0] = 1.50011; // x - old value, y - new value 
    x[1] = 2.; y[1] = 2.0000001; 

    __m128d sx = _mm_load_pd(x); 
    __m128d sy = _mm_load_pd(y); 

    // sign mask to compute fabs() 
    __m128d sign_mask = _mm_set1_pd(-0.); 
    // |x-y| 
    __m128d absval = _mm_andnot_pd(sign_mask, _mm_sub_pd(sx, sy)); 
    // mask of |x-y| < p 
    __m128d mask = _mm_cmplt_pd(absval, sp); 
    // sres = |x-y| < p ? x : y; 
    __m128d sres = _mm_or_pd(
      _mm_and_pd(mask, sx), _mm_andnot_pd(mask, sy)); 
    _mm_store_pd(res, sres); 
    std::cerr << "res=" << res[0] << "," << res[1] << std::endl; 
    return 0; 
} 

編譯:

g++ -std=c++11 -msse4 test.cpp 

我們首先計算晶圓廠(XY),比較P,並結合X,Y使用獲得了面具 。

有沒有人看到更有效的方式來編碼?謝謝。

+0

你可以嘗試使用'BLENDVPD'('_mm_blendv_pd'),看看你是否有更好的表現。 – ElderBug

+0

很好,謝謝。我不知道這條指令。 – Cattus

+0

@ElderBug:blendv指令通常翻譯成3個uops,所以我猜它的吞吐量不會更快。 – stgatilov

回答

1

有一種方法,使這項algoritm快一點,但它可以降低精確度:

// d = x - y; 
__m128d diff = _mm_sub_pd(sx, sy); 
// mask of |y - x| < p 
__m128d mask = _mm_cmplt_pd(_mm_andnot_pd(sign_mask, diff), sp); 
// sres = y + (|y - x| < p) ? (x - y) : 0; 
__m128d sres = _mm_add_pd(sy, _mm_and_pd(mask, diff)); 

另一種方式 - 使用AVX和/或單精度的。