我有 AVX(没有 AVX2 或 AVX-512)。我有一个带有 32 位值的 vector (仅使用了 4 个最低位,其余始终为零):

[ 1010, 0000, 0000, 0000, 0000, 1010, 1010, 0000]

在内部,由于按位运算,我将 vector 保留为 __m256,并且位表示“浮点数”。我需要从 vector 中导出单个 8 位数字,其中包含 1 表示非零,0 表示零位。

所以对于上面的例子,我需要 8 位数字:10000110
我有想法使用 _mm256_cmp_ps 然后 _mm256_movemask_ps 。但是,对于 cmp,我不知道它是否可以正常工作,如果数字不完全是浮点数并且可以是任何“垃圾”。在这种情况下,cmp 使用哪个操作数?

或者还有其他解决方案吗?

最佳答案

从概念上讲,您正在做的事情应该有效。具有高 24 位零的浮点数是有效浮点数。然而,他们是不正常的。

虽然它应该可以工作,但有两个潜在的问题:

  • 如果将 FP 模式设置为将非正规数刷新为零,则它们都将被视为零。 (因此,打破这种方法)
  • 因为这些是非正规的,你最终可能会因硬件是否可以本地处理它们而遭受巨大的性能损失。


  • 替代方法:

    由于高 24 位为零,您可以对它们进行归一化。然后进行浮点比较。

    (警告:未经测试的代码)
    int to_mask(__m256 data){
        const __m256 MASK = _mm256_set1_ps(8388608.);  //  2^23
        data = _mm256_or_ps(data, MASK);
        data = _mm256_cmp_ps(data, MASK, _CMP_NEQ_UQ);
        return _mm256_movemask_ps(data);
    }
    

    在这里, data 是您的输入,其中每个“浮点数”的高 24 位为零。让我们将这些 8 位整数中的每一个都称为 x

    2^23 的 OR'ing 设置浮点数的尾数,使其成为具有 2^23 + x 值的标准化浮点数。

    然后将 2^23float 进行比较 - 只有当 x 非零时才会给出 1。

    关于c - SIMD - AVX - 用非零值而不是最高位屏蔽,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57610688/

    10-11 19:43
    查看更多