首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SSE rms计算

SSE rms计算
EN

Stack Overflow用户
提问于 2013-04-10 04:40:37
回答 1查看 886关注 0票数 4

我想用Intel sse内部函数计算rms。如下所示:

代码语言:javascript
复制
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?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-10 05:22:39

您可以通过将值与其本身进行比较来测试NaN的值。如果x是NaN,则x == x将返回false。因此,对于4 x浮点值的SSE向量,vx:

代码语言:javascript
复制
    vmask = _mm_cmpeq_ps(vx, vx);

将为vx中的NaN元素提供全0的掩码向量,为非NaN元素提供全1的掩码向量。你可以用这个面罩把NaNs清零。您还可以使用掩码来计算有效数据点的数量,方法是将其视为32位整数的向量并进行累加。

下面是一个有效的、经过测试的示例--请注意,它假设n是4的倍数,a、b不是16字节对齐的,还需要注意它需要SSE4。

代码语言:javascript
复制
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;
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15912072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档