c - 上证有效值计算

标签 c x86 nan sse simd

我想用 Intel sse intrinsic 计算 rms。 像这样:

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怎么算?

最佳答案

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

    vmask = _mm_cmpeq_ps(vx, vx);

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

这是一个经过测试的有效示例 - 请注意,它假定 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;
}

关于c - 上证有效值计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15912072/

相关文章:

c++ - 访问与某个位置直接相邻的多维数组中的所有位置?

c - 使用#define 设置变量类型

程序集 - 将 float 舍入到 -∞ 的 0.001 精度

Javascript 数组意外地被 NaN 填充

c - 始终包含标准 header 是一个好习惯吗?

c - OpenSSL 1.1.0 : HMAC_CTX must now be allocated, 为什么?

assembly - 新的 X86_64 处理器寄存器的名称是什么?

c - unsigned long long int 的按位运算超过 32 位时不适用

pandas - 在 Pandas 系列中填充连续的 NaN

Python 将 NAN 更改为零向量