我有 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 位零的浮点数是有效浮点数。然而,他们是不正常的。
虽然它应该可以工作,但有两个潜在的问题:
替代方法:
由于高 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^23
与 float
进行比较 - 只有当 x
非零时才会给出 1。关于c - SIMD - AVX - 用非零值而不是最高位屏蔽,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57610688/