【发布时间】:2020-02-26 13:10:29
【问题描述】:
如果 float32 数字数组的值不为零,如何使用 AVX 将它们变为 1?
例如:-0.2134f, -1.23f, -0.0f, 12.0f ...
变成1.0f, 1.0f, 0.0f, 1.0f ...
我认为,我们应该将_mm256_or_ps 与其他指令结合起来,但是如何?
【问题讨论】:
标签: c++ sse intrinsics avx
如果 float32 数字数组的值不为零,如何使用 AVX 将它们变为 1?
例如:-0.2134f, -1.23f, -0.0f, 12.0f ...
变成1.0f, 1.0f, 0.0f, 1.0f ...
我认为,我们应该将_mm256_or_ps 与其他指令结合起来,但是如何?
【问题讨论】:
标签: c++ sse intrinsics avx
我想出的第一个想法是将这些值与 0 进行比较,然后将其与一个满是 1 的寄存器进行与运算:
y = _mm256_and_ps(_mm256_cmp_ps(_mm256_setzero_ps(), x, _CMP_NEQ_OQ), _mm256_set1_ps(1.f));
这会将 x 为 0 的地方的所有 1 与一堆 0 和幸运的是 IEEE 754 零也是整数零。其他值将得到一个浮点 1 与一堆 1 的 AND 运算,因此是一个恒等运算。
【讨论】:
可能是vcmpps with a NE predicate,那么带有1.0f 位模式的_mm256_and_ps 是您最好的选择。
一个错误的比较谓词给你一个全零位模式,它也方便地表示0.0f。
全1 & 1.0f = 1.0f。
总共 2 条单指令。仅当您想要 0.0f 以外的值用于 false 情况时,将比较结果用于变量混合会更好。
【讨论】:
_mm256_cmpne_ps 不存在。对于 AVX,只有通用的 _mm256_cmp_ps 内在函数将比较函数作为立即值参数。我也没有真正意识到这一点。
VCMPNEQ_OQPS 这样的助记符,但是是的,英特尔决定只为新的 AVX 谓词创建一个通用的内在函数。当我需要 vcmpps 内在函数时,我总是需要查找它。