2013-04-09 24 views
4

我想用英特尔sse内在计算均方根。 这样的:上证所有效值计算

float rms(float *a, float *b , int l) 
{ 
    int n=0; 
    float r=0.0; 
    for(int i=0;i<l;i++) 
    { 
     if(finitef(a[i]) && finitef(b[i])) 
     { 
      n++; 
      tmp = a[i] - b[i]; 
      r += tmp*tmp; 
     } 
    } 
    r /= n; 
    return r; 
} 

但是如何检查哪些元素是NaN?以及如何计算n?

+1

_mm_cmpord_ps(a [i],b [i])也许?你会用n + = 4来计算n。请注意,编译器可以自己矢量化这个循环。还要注意的是,finitef并不完全检查NaN。 – 2013-04-09 21:24:58

+0

请注意,此功能不计算RMS - 它计算均方差。 – 2013-04-10 08:55:56

+0

你是对的,但SSE中的sqrt也是个问题,我想: -/ – Roby 2013-04-11 16:46:46

回答

5

您可以通过比较自己的值来测试NaN的值。如果x是NaN,则x == x将返回false。因此,对于4×浮点值的SSE向量,VX:

vmask = _mm_cmpeq_ps(vx, vx); 

会给你全0在VX NaN的元素和全1对于非NaN的元素面膜载体。您可以使用掩码来清零NaN。您还可以使用该掩码将有效数据点的数量视为32位整数和累加的向量来计数。

这里是一个经过测试的示例 - 注意它假定n是4的倍数,a,b不是16字节对齐的,并且还要注意它需要SSE4。

float rms(const float *a, const float *b , int n) 
{ 
    int count; 
    float sum; 
    __m128i vcount = _mm_set1_epi32(0); 
    __m128 vsum = _mm_set1_ps(0.0f); 
    assert((n & 3) == 0); 
    for (int i = 0; i < n; i += 4) 
    { 
     __m128 va = _mm_loadu_ps(&a[i]); 
     __m128 vb = _mm_loadu_ps(&b[i]); 
     __m128 vmaska = _mm_cmpeq_ps(va, va); 
     __m128 vmaskb = _mm_cmpeq_ps(vb, vb); 
     __m128 vmask = _mm_and_ps(vmaska, vmaskb); 
     __m128 vtmp = _mm_sub_ps(va, vb); 
     vtmp = _mm_and_ps(vtmp, vmask); 
     vtmp = _mm_mul_ps(vtmp, vtmp); 
     vsum = _mm_add_ps(vsum, vtmp); 
     vcount = _mm_sub_epi32(vcount, (__m128i)vmask); 
    } 
    vsum = _mm_hadd_ps(vsum, vsum); 
    vsum = _mm_hadd_ps(vsum, vsum); 
    _mm_store_ss(&sum, vsum); 
    vcount = _mm_hadd_epi32(vcount, vcount); 
    vcount = _mm_hadd_epi32(vcount, vcount); 
    count = _mm_extract_epi32(vcount, 0); 
    return count > 0 ? sum/(float)count : 0.0f; 
} 
+0

谢谢,但如果我想它像“vmask = _mm_cmpeq_ps(vx,vx);” enxt的步骤是将这4个元素添加到一个我认为与_mm_hadd_ps调用两次?但后来我有我的总和nan值。所以我第一次从矢量中删除这些nans? : -/ – Roby 2013-04-10 06:11:08

+2

否 - 使用掩码将NaN归零。也不要在循环之后进行任何水平添加。您也可以使用掩码来计算有效数据点的数量。 – 2013-04-10 06:40:24

+0

@Roby:见上 - 我现在已经添加了一个完整的工作实现。 – 2013-04-10 08:54:19